/// <summary> /// Returns the proper ShardManagementException corresponding to given error code in /// <paramref name="result"/> for ShardMap operations. /// </summary> /// <param name="result">Operation result object.</param> /// <param name="shardMap">Shard map object.</param> /// <param name="location">Location of operation.</param> /// <param name="errorCategory">Error category to use for raised errors.</param> /// <param name="operationName">Operation being performed.</param> /// <param name="storedProcName">Stored procedure being executed.</param> /// <returns>ShardManagementException to be raised.</returns> internal static ShardManagementException OnRecoveryErrorLocal( IStoreResults result, IStoreShardMap shardMap, ShardLocation location, ShardManagementErrorCategory errorCategory, string operationName, string storedProcName) { switch (result.Result) { case StoreResult.ShardMapDoesNotExist: return(new ShardManagementException( errorCategory, ShardManagementErrorCode.ShardMapDoesNotExist, Errors._Store_ShardMap_DoesNotExistLocal, shardMap.Name, location, storedProcName, operationName)); case StoreResult.StoreVersionMismatch: case StoreResult.MissingParametersForStoredProcedure: default: return(StoreOperationErrorHandler.OnCommonErrorLocal( result, location, operationName, storedProcName)); } }
/// <summary> /// Constructs request for obtaining mapping from GSM based on given key. /// </summary> /// <param name="shardMapManager">Shard map manager.</param> /// <param name="operationName">Operation being executed.</param> /// <param name="shardMap">Local shard map.</param> /// <param name="mapping">Mapping whose Id will be used.</param> /// <param name="errorCategory">Error category.</param> internal FindMappingByIdGlobalOperation(ShardMapManager shardMapManager, string operationName, IStoreShardMap shardMap, IStoreMapping mapping, ShardManagementErrorCategory errorCategory) : base(shardMapManager.Credentials, shardMapManager.RetryPolicy, operationName) { _manager = shardMapManager; _shardMap = shardMap; _mapping = mapping; _errorCategory = errorCategory; }
/// <summary> /// Looks up the key value and returns the corresponding mapping. /// </summary> /// <typeparam name="TMapping">Mapping type.</typeparam> /// <typeparam name="TKey">Key type.</typeparam> /// <param name="key">Input key value.</param> /// <param name="useCache">Whether to use cache for lookups.</param> /// <param name="constructMapping">Delegate to construct a mapping object.</param> /// <param name="errorCategory">Category under which errors must be thrown.</param> /// <returns>Mapping that contains the key value.</returns> protected TMapping Lookup <TMapping, TKey>( TKey key, bool useCache, Func <ShardMapManager, ShardMap, IStoreMapping, TMapping> constructMapping, ShardManagementErrorCategory errorCategory) where TMapping : class, IShardProvider { ShardKey sk = new ShardKey(ShardKey.ShardKeyTypeFromType(typeof(TKey)), key); if (useCache) { ICacheStoreMapping cachedMapping = this.Manager.Cache.LookupMappingByKey(this.ShardMap.StoreShardMap, sk); if (cachedMapping != null) { return(constructMapping(this.Manager, this.ShardMap, cachedMapping.Mapping)); } } // Cache-miss, find mapping for given key in GSM. TMapping m = null; IStoreResults gsmResult; Stopwatch stopwatch = Stopwatch.StartNew(); using (IStoreOperationGlobal op = this.Manager.StoreOperationFactory.CreateFindMappingByKeyGlobalOperation( this.Manager, "Lookup", this.ShardMap.StoreShardMap, sk, CacheStoreMappingUpdatePolicy.OverwriteExisting, errorCategory, true, false)) { gsmResult = op.Do(); } stopwatch.Stop(); Tracer.TraceVerbose( TraceSourceConstants.ComponentNames.BaseShardMapper, "Lookup", "Lookup key from GSM complete; Key type : {0}; Result: {1}; Duration: {2}", typeof(TKey), gsmResult.Result, stopwatch.Elapsed); // If we could not locate the mapping, we return null and do nothing here. if (gsmResult.Result != StoreResult.MappingNotFoundForKey) { return(gsmResult.StoreMappings.Select(sm => constructMapping(this.Manager, this.ShardMap, sm)).Single()); } return(m); }
/// <summary> /// Constructs request for obtaining all the mappings from GSM based on given shard and mappings. /// </summary> /// <param name="shardMapManager">Shard map manager.</param> /// <param name="operationName">Operation being executed.</param> /// <param name="shardMap">Local shard map.</param> /// <param name="shard">Local shard.</param> /// <param name="range">Optional range to get mappings from.</param> /// <param name="errorCategory">Error category.</param> /// <param name="cacheResults">Whether to cache the results of the operation.</param> /// <param name="ignoreFailure">Ignore shard map not found error.</param> internal GetMappingsByRangeGlobalOperation(ShardMapManager shardMapManager, string operationName, IStoreShardMap shardMap, IStoreShard shard, ShardRange range, ShardManagementErrorCategory errorCategory, bool cacheResults, bool ignoreFailure) : base(shardMapManager.Credentials, shardMapManager.RetryPolicy, operationName) { _manager = shardMapManager; _shardMap = shardMap; _shard = shard; _range = range; _errorCategory = errorCategory; _cacheResults = cacheResults; _ignoreFailure = ignoreFailure; }
/// <summary> /// Constructs request to lock or unlock given mappings in GSM. /// </summary> /// <param name="shardMapManager">Shard map manager object.</param> /// <param name="operationName">Operation name, useful for diagnostics.</param> /// <param name="shardMap">Shard map to add.</param> /// <param name="mapping">Mapping to lock or unlock. Null means all mappings.</param> /// <param name="lockOwnerId">Lock owner.</param> /// <param name="lockOpType">Lock operation type.</param> /// <param name="errorCategory">Error category.</param> internal LockOrUnLockMappingsGlobalOperation(ShardMapManager shardMapManager, string operationName, IStoreShardMap shardMap, IStoreMapping mapping, Guid lockOwnerId, LockOwnerIdOpType lockOpType, ShardManagementErrorCategory errorCategory) : base(shardMapManager.Credentials, shardMapManager.RetryPolicy, operationName) { _shardMapManager = shardMapManager; _shardMap = shardMap; _mapping = mapping; _lockOwnerId = lockOwnerId; _lockOpType = lockOpType; _errorCategory = errorCategory; Debug.Assert(mapping != null || (lockOpType == LockOwnerIdOpType.UnlockAllMappingsForId || lockOpType == LockOwnerIdOpType.UnlockAllMappings)); }
/// <summary> /// Constructs a global store exception object based on the given input parameters. /// </summary> /// <param name="category">Error category.</param> /// <param name="storeException">Underlying store exception.</param> /// <param name="operationName">Operation name.</param> /// <returns> /// ShardManagementException corresponding to the given store exception. /// </returns> internal static ShardManagementException GetStoreExceptionGlobal( ShardManagementErrorCategory category, StoreException storeException, string operationName) { return(new ShardManagementException( category, ShardManagementErrorCode.StorageOperationFailure, Errors._Store_SqlExceptionGlobal, storeException.InnerException != null ? storeException.InnerException.Message : storeException.Message, storeException, operationName)); }
/// <summary> /// Constructs request for obtaining mapping from GSM based on given key. /// </summary> /// <param name="shardMapManager">Shard map manager.</param> /// <param name="operationName">Operation being executed.</param> /// <param name="shardMap">Local shard map.</param> /// <param name="mapping">Mapping whose Id will be used.</param> /// <param name="errorCategory">Error category.</param> /// <returns>The store operation.</returns> public virtual IStoreOperationGlobal CreateFindMappingByIdGlobalOperation( ShardMapManager shardMapManager, string operationName, IStoreShardMap shardMap, IStoreMapping mapping, ShardManagementErrorCategory errorCategory) { return(new FindMappingByIdGlobalOperation( shardMapManager, operationName, shardMap, mapping, errorCategory)); }
/// <summary> /// Given a key value, obtains a SqlConnection to the shard in the mapping /// that contains the key value. /// </summary> /// <typeparam name="TMapping">Mapping type.</typeparam> /// <typeparam name="TKey">Key type.</typeparam> /// <param name="key">Input key value.</param> /// <param name="constructMapping">Delegate to construct a mapping object.</param> /// <param name="errorCategory">Error category.</param> /// <param name="connectionString"> /// Connection string with credential information, the DataSource and Database are /// obtained from the results of the lookup operation for key. /// </param> /// <param name="options">Options for validation operations to perform on opened connection.</param> /// <returns>An opened SqlConnection.</returns> protected SqlConnection OpenConnectionForKey <TMapping, TKey>( TKey key, Func <ShardMapManager, ShardMap, IStoreMapping, TMapping> constructMapping, ShardManagementErrorCategory errorCategory, string connectionString, ConnectionOptions options = ConnectionOptions.Validate) where TMapping : class, IShardProvider { return(this.OpenConnectionForKey <TMapping, TKey>( key, constructMapping, errorCategory, connectionString, null, options)); }
/// <summary> /// Asynchronously finds the mapping in store for OpenConnectionForKey operation. /// </summary> /// <param name="sk">Key to find.</param> /// <param name="policy">Cache update policy.</param> /// <param name="errorCategory">Error category.</param> /// <returns>Task with the Mapping corresponding to the given key if found as the result.</returns> private async Task <IStoreMapping> LookupMappingForOpenConnectionForKeyAsync( ShardKey sk, CacheStoreMappingUpdatePolicy policy, ShardManagementErrorCategory errorCategory) { IStoreResults gsmResult; Stopwatch stopwatch = Stopwatch.StartNew(); using (IStoreOperationGlobal op = this.Manager.StoreOperationFactory.CreateFindMappingByKeyGlobalOperation( this.Manager, "Lookup", this.ShardMap.StoreShardMap, sk, policy, errorCategory, true, false)) { gsmResult = await op.DoAsync().ConfigureAwait(false); } stopwatch.Stop(); Tracer.TraceVerbose( TraceSourceConstants.ComponentNames.BaseShardMapper, "LookupMappingForOpenConnectionForKeyAsync", "Lookup key from GSM complete; Key type : {0}; Result: {1}; Duration: {2}", sk.DataType, gsmResult.Result, stopwatch.Elapsed); // If we could not locate the mapping, we throw. if (gsmResult.Result == StoreResult.MappingNotFoundForKey) { throw new ShardManagementException( errorCategory, ShardManagementErrorCode.MappingNotFoundForKey, Errors._Store_ShardMapper_MappingNotFoundForKeyGlobal, this.ShardMap.Name, StoreOperationRequestBuilder.SpFindShardMappingByKeyGlobal, "LookupMappingForOpenConnectionForKeyAsync"); } else { return(gsmResult.StoreMappings.Single()); } }
/// <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> /// Gets the lock owner of a mapping. /// </summary> /// <param name="mapping">The mapping</param> /// <param name="errorCategory">Error category to use for the store operation</param> /// <returns>Lock owner for the mapping.</returns> internal Guid GetLockOwnerForMapping <TMapping>(TMapping mapping, ShardManagementErrorCategory errorCategory) where TMapping : class, IShardProvider, IMappingInfoProvider { this.EnsureMappingBelongsToShardMap <TMapping>(mapping, "LookupLockOwner", "mapping"); IStoreResults result; using (IStoreOperationGlobal op = this.Manager.StoreOperationFactory.CreateFindMappingByIdGlobalOperation( this.Manager, "LookupLockOwner", this.ShardMap.StoreShardMap, mapping.StoreMapping, errorCategory)) { result = op.Do(); } return(result.StoreMappings.Single().LockOwnerId); }
/// <summary> /// Constructs request to lock or unlock given mappings in GSM. /// </summary> /// <param name="shardMapManager">Shard map manager object.</param> /// <param name="operationName">Operation name, useful for diagnostics.</param> /// <param name="shardMap">Shard map to add.</param> /// <param name="mapping">Mapping to lock or unlock. Null means all mappings.</param> /// <param name="lockOwnerId">Lock owner.</param> /// <param name="lockOpType">Lock operation type.</param> /// <param name="errorCategory">Error category.</param> /// <returns>The store operation.</returns> public virtual IStoreOperationGlobal CreateLockOrUnLockMappingsGlobalOperation( ShardMapManager shardMapManager, string operationName, IStoreShardMap shardMap, IStoreMapping mapping, Guid lockOwnerId, LockOwnerIdOpType lockOpType, ShardManagementErrorCategory errorCategory) { return(new LockOrUnLockMappingsGlobalOperation( shardMapManager, operationName, shardMap, mapping, lockOwnerId, lockOpType, errorCategory)); }
/// <summary> /// Constructs request for obtaining mapping from GSM based on given key. /// </summary> /// <param name="shardMapManager">Shard map manager.</param> /// <param name="operationName">Operation being executed.</param> /// <param name="shardMap">Local shard map.</param> /// <param name="key">Key for lookup operation.</param> /// <param name="policy">Policy for cache update.</param> /// <param name="errorCategory">Error category.</param> /// <param name="cacheResults">Whether to cache the results of the operation.</param> /// <param name="ignoreFailure">Ignore shard map not found error.</param> protected internal FindMappingByKeyGlobalOperation( ShardMapManager shardMapManager, string operationName, IStoreShardMap shardMap, ShardKey key, CacheStoreMappingUpdatePolicy policy, ShardManagementErrorCategory errorCategory, bool cacheResults, bool ignoreFailure) : base(shardMapManager.Credentials, shardMapManager.RetryPolicy, operationName) { _manager = shardMapManager; _shardMap = shardMap; _key = key; _policy = policy; _errorCategory = errorCategory; _cacheResults = cacheResults; _ignoreFailure = ignoreFailure; }
/// <summary> /// Returns the proper ShardManagementException corresponding to given error code in /// <paramref name="result"/> for ShardMap operations. /// </summary> /// <param name="result">Operation result object.</param> /// <param name="shardMap">Shard map object.</param> /// <param name="location">Location of LSM operation.</param> /// <param name="errorCategory">Error category to use for raised errors.</param> /// <param name="operationName">Operation being performed.</param> /// <param name="storedProcName">Stored procedure being executed.</param> /// <returns>ShardManagementException to be raised.</returns> internal static ShardManagementException OnShardMapErrorLocal( IStoreResults result, IStoreShardMap shardMap, ShardLocation location, ShardManagementErrorCategory errorCategory, string operationName, string storedProcName) { switch (result.Result) { case StoreResult.UnableToKillSessions: return(new ShardManagementException( errorCategory, ShardManagementErrorCode.MappingsKillConnectionFailure, Errors._Store_ShardMapper_UnableToKillSessions, location, shardMap.Name, operationName, storedProcName, location)); case StoreResult.StoreVersionMismatch: case StoreResult.MissingParametersForStoredProcedure: case StoreResult.ShardDoesNotExist: // ShardDoesNotExist on local shard map can only occur in Recovery scenario. // For normal UpdateShard operation, we will get this error from GSM operation first. return(new ShardManagementException( ShardManagementErrorCategory.Recovery, ShardManagementErrorCode.ShardDoesNotExist, Errors._Store_Validate_ShardDoesNotExist, location, shardMap.Name, operationName, storedProcName)); default: return(StoreOperationErrorHandler.OnCommonErrorLocal( result, location, operationName, storedProcName)); } }
/// <summary> /// Constructs request for obtaining mapping from GSM based on given key. /// </summary> /// <param name="shardMapManager">Shard map manager.</param> /// <param name="operationName">Operation being executed.</param> /// <param name="shardMap">Local shard map.</param> /// <param name="key">Key for lookup operation.</param> /// <param name="policy">Policy for cache update.</param> /// <param name="errorCategory">Error category.</param> /// <param name="cacheResults">Whether to cache the results of the operation.</param> /// <param name="ignoreFailure">Ignore shard map not found error.</param> /// <returns>The store operation.</returns> public virtual IStoreOperationGlobal CreateFindMappingByKeyGlobalOperation( ShardMapManager shardMapManager, string operationName, IStoreShardMap shardMap, ShardKey key, CacheStoreMappingUpdatePolicy policy, ShardManagementErrorCategory errorCategory, bool cacheResults, bool ignoreFailure) { return(new FindMappingByKeyGlobalOperation( shardMapManager, operationName, shardMap, key, policy, errorCategory, cacheResults, ignoreFailure)); }
/// <summary> /// Constructs request for obtaining all the mappings from GSM based on given shard and mappings. /// </summary> /// <param name="shardMapManager">Shard map manager.</param> /// <param name="operationName">Operation being executed.</param> /// <param name="shardMap">Local shard map.</param> /// <param name="shard">Local shard.</param> /// <param name="range">Optional range to get mappings from.</param> /// <param name="errorCategory">Error category.</param> /// <param name="cacheResults">Whether to cache the results of the operation.</param> /// <param name="ignoreFailure">Ignore shard map not found error.</param> /// <returns>The store operation.</returns> public virtual IStoreOperationGlobal CreateGetMappingsByRangeGlobalOperation( ShardMapManager shardMapManager, string operationName, IStoreShardMap shardMap, IStoreShard shard, ShardRange range, ShardManagementErrorCategory errorCategory, bool cacheResults, bool ignoreFailure) { return(new GetMappingsByRangeGlobalOperation( shardMapManager, operationName, shardMap, shard, range, errorCategory, cacheResults, ignoreFailure)); }
/// <summary> /// Creates request to add shard to given shard map. /// </summary> /// <param name="shardMapManager">Shard map manager object.</param> /// <param name="operationId">Operation id.</param> /// <param name="undoStartState">State from which Undo operation starts.</param> /// <param name="operationCode">Store operation code.</param> /// <param name="shardMap">Shard map for which to update mapping.</param> /// <param name="mappingSource">Mapping to update.</param> /// <param name="mappingTarget">Updated mapping.</param> /// <param name="patternForKill">Pattern for kill commands.</param> /// <param name="lockOwnerId">Id of lock owner.</param> /// <param name="originalShardVersionRemoves">Original shard version for removes.</param> /// <param name="originalShardVersionAdds">Original shard version for adds.</param> /// <param name="killConnection">Whether to kill open connections.</param> internal UpdateMappingOperation( ShardMapManager shardMapManager, Guid operationId, StoreOperationState undoStartState, StoreOperationCode operationCode, IStoreShardMap shardMap, IStoreMapping mappingSource, IStoreMapping mappingTarget, string patternForKill, Guid lockOwnerId, Guid originalShardVersionRemoves, Guid originalShardVersionAdds, bool killConnection) : base( shardMapManager, operationId, undoStartState, operationCode, originalShardVersionRemoves, originalShardVersionAdds) { _shardMap = shardMap; _mappingSource = mappingSource; _mappingTarget = mappingTarget; _lockOwnerId = lockOwnerId; _errorCategory = (operationCode == StoreOperationCode.UpdateRangeMapping || operationCode == StoreOperationCode.UpdateRangeMappingWithOffline) ? ShardManagementErrorCategory.RangeShardMap : ShardManagementErrorCategory.ListShardMap; _updateLocation = _mappingSource.StoreShard.Id != _mappingTarget.StoreShard.Id; _fromOnlineToOffline = operationCode == StoreOperationCode.UpdatePointMappingWithOffline || operationCode == StoreOperationCode.UpdateRangeMappingWithOffline; _patternForKill = patternForKill; _killConnection = killConnection; }
/// <summary> /// Creates request to add shard to given shard map. /// </summary> /// <param name="shardMapManager">Shard map manager object.</param> /// <param name="operationId">Operation id.</param> /// <param name="undoStartState">State from which Undo operation starts.</param> /// <param name="operationCode">Store operation code.</param> /// <param name="shardMap">Shard map for which to add mapping.</param> /// <param name="mapping">Mapping to add.</param> /// <param name="originalShardVersionAdds">Original shard version.</param> internal AddMappingOperation( ShardMapManager shardMapManager, Guid operationId, StoreOperationState undoStartState, StoreOperationCode operationCode, IStoreShardMap shardMap, IStoreMapping mapping, Guid originalShardVersionAdds) : base( shardMapManager, operationId, undoStartState, operationCode, default(Guid), originalShardVersionAdds) { _shardMap = shardMap; _mapping = mapping; _errorCategory = operationCode == StoreOperationCode.AddRangeMapping ? ShardManagementErrorCategory.RangeShardMap : ShardManagementErrorCategory.ListShardMap; }
/// <summary> /// Returns the proper ShardManagementException corresponding to given error code in /// <paramref name="result"/> for ShardMap operations. /// </summary> /// <param name="result">Operation result object.</param> /// <param name="shardMap">Shard map object.</param> /// <param name="shard">Shard object.</param> /// <param name="errorCategory">Error category to use for raised errors.</param> /// <param name="operationName">Operation being performed.</param> /// <param name="storedProcName">Stored procedure being executed.</param> /// <returns>ShardManagementException to be raised.</returns> internal static ShardManagementException OnRecoveryErrorGlobal( IStoreResults result, IStoreShardMap shardMap, IStoreShard shard, ShardManagementErrorCategory errorCategory, string operationName, string storedProcName) { switch (result.Result) { case StoreResult.ShardLocationExists: return(new ShardManagementException( errorCategory, ShardManagementErrorCode.ShardLocationAlreadyExists, Errors._Store_Shard_LocationAlreadyExistsGlobal, shard.Location, shardMap.Name, storedProcName, operationName)); case StoreResult.ShardMapExists: Debug.Assert(shardMap != null); return(new ShardManagementException( errorCategory, ShardManagementErrorCode.ShardMapAlreadyExists, Errors._Store_ShardMap_AlreadyExistsGlobal, shardMap.Name, storedProcName, operationName)); case StoreResult.StoreVersionMismatch: case StoreResult.MissingParametersForStoredProcedure: default: return(StoreOperationErrorHandler.OnCommonErrorGlobal( result, operationName, storedProcName)); } }
/// <summary> /// Creates request to add shard to given shard map. /// </summary> /// <param name="shardMapManager">Shard map manager object.</param> /// <param name="operationId">Operation id.</param> /// <param name="undoStartState">State from which Undo operation starts.</param> /// <param name="operationCode">Store operation code.</param> /// <param name="shardMap">Shard map from which to remove mapping.</param> /// <param name="mapping">Mapping to add.</param> /// <param name="lockOwnerId">Id of lock owner.</param> /// <param name="originalShardVersionRemoves">Original shard version.</param> internal RemoveMappingOperation( ShardMapManager shardMapManager, Guid operationId, StoreOperationState undoStartState, StoreOperationCode operationCode, IStoreShardMap shardMap, IStoreMapping mapping, Guid lockOwnerId, Guid originalShardVersionRemoves) : base( shardMapManager, operationId, undoStartState, operationCode, originalShardVersionRemoves, default(Guid)) { _shardMap = shardMap; _mapping = mapping; _lockOwnerId = lockOwnerId; _errorCategory = operationCode == StoreOperationCode.RemoveRangeMapping ? ShardManagementErrorCategory.RangeShardMap : ShardManagementErrorCategory.ListShardMap; }
/// <summary> /// Constructs request for obtaining all the mappings from GSM based on given shard and mappings. /// </summary> /// <param name="shardMapManager">Shard map manager.</param> /// <param name="operationName">Operation being executed.</param> /// <param name="shardMap">Local shard map.</param> /// <param name="shard">Local shard.</param> /// <param name="range">Optional range to get mappings from.</param> /// <param name="errorCategory">Error category.</param> /// <param name="cacheResults">Whether to cache the results of the operation.</param> /// <param name="ignoreFailure">Ignore shard map not found error.</param> /// <returns>The store operation.</returns> public virtual IStoreOperationGlobal CreateGetMappingsByRangeGlobalOperation( ShardMapManager shardMapManager, string operationName, IStoreShardMap shardMap, IStoreShard shard, ShardRange range, ShardManagementErrorCategory errorCategory, bool cacheResults, bool ignoreFailure) { return new GetMappingsByRangeGlobalOperation( shardMapManager, operationName, shardMap, shard, range, errorCategory, cacheResults, ignoreFailure); }
/// <summary> /// Initializes a new instance /// </summary> public StubFindMappingByKeyGlobalOperation(ShardMapManager shardMapManager, string operationName, IStoreShardMap shardMap, ShardKey key, CacheStoreMappingUpdatePolicy policy, ShardManagementErrorCategory errorCategory, bool cacheResults, bool ignoreFailure) : base(shardMapManager, operationName, shardMap, key, policy, errorCategory, cacheResults, ignoreFailure) { this.InitializeStub(); }
/// <summary> /// Sets the stub of StoreOperationFactory.CreateFindMappingByKeyGlobalOperation(ShardMapManager shardMapManager, String operationName, IStoreShardMap shardMap, ShardKey key, CacheStoreMappingUpdatePolicy policy, ShardManagementErrorCategory errorCategory, Boolean cacheResults, Boolean ignoreFailure) /// </summary> public override IStoreOperationGlobal CreateFindMappingByKeyGlobalOperation(ShardMapManager shardMapManager, string operationName, IStoreShardMap shardMap, ShardKey key, CacheStoreMappingUpdatePolicy policy, ShardManagementErrorCategory errorCategory, bool cacheResults, bool ignoreFailure) { Func<ShardMapManager, string, IStoreShardMap, ShardKey, CacheStoreMappingUpdatePolicy, ShardManagementErrorCategory, bool, bool, IStoreOperationGlobal> func1 = this.CreateFindMappingByKeyGlobalOperationShardMapManagerStringIStoreShardMapShardKeyCacheStoreMappingUpdatePolicyShardManagementErrorCategoryBooleanBoolean; if (func1 != null) return func1(shardMapManager, operationName, shardMap, key, policy, errorCategory, cacheResults, ignoreFailure); if (this.___callBase) return base.CreateFindMappingByKeyGlobalOperation(shardMapManager, operationName, shardMap, key, policy, errorCategory, cacheResults, ignoreFailure); return this.InstanceBehavior.Result<StubStoreOperationFactory, IStoreOperationGlobal>(this, "CreateFindMappingByKeyGlobalOperation"); }
/// <summary> /// Given a key value, asynchronously obtains a SqlConnection to the shard in the mapping /// that contains the key value. /// </summary> /// <typeparam name="TMapping">Mapping type.</typeparam> /// <typeparam name="TKey">Key type.</typeparam> /// <param name="key">Input key value.</param> /// <param name="constructMapping">Delegate to construct a mapping object.</param> /// <param name="errorCategory">Error category.</param> /// <param name="connectionString"> /// Connection string with credential information, the DataSource and Database are /// obtained from the results of the lookup operation for key. /// </param> /// <param name="secureCredential">Secure SQL Credential.</param> /// <param name="options">Options for validation operations to perform on opened connection.</param> /// <returns>A task encapsulating an opened SqlConnection as the result.</returns> protected async Task <SqlConnection> OpenConnectionForKeyAsync <TMapping, TKey>( TKey key, Func <ShardMapManager, ShardMap, IStoreMapping, TMapping> constructMapping, ShardManagementErrorCategory errorCategory, string connectionString, SqlCredential secureCredential, ConnectionOptions options = ConnectionOptions.Validate) where TMapping : class, IShardProvider { ShardKey sk = new ShardKey(ShardKey.ShardKeyTypeFromType(typeof(TKey)), key); // Try to find the mapping within the cache. ICacheStoreMapping csm = this.Manager.Cache.LookupMappingByKey(this.ShardMap.StoreShardMap, sk); IStoreMapping sm; if (csm != null) { sm = csm.Mapping; } else { sm = await this.LookupMappingForOpenConnectionForKeyAsync( sk, CacheStoreMappingUpdatePolicy.OverwriteExisting, errorCategory).ConfigureAwait(false); } SqlConnection result; bool lookupMappingOnEx = false; CacheStoreMappingUpdatePolicy cacheUpdatePolicyOnEx = CacheStoreMappingUpdatePolicy.OverwriteExisting; try { // Initially attempt to connect based on lookup results from either cache or GSM. result = await this.ShardMap.OpenConnectionAsync( constructMapping(this.Manager, this.ShardMap, sm), connectionString, secureCredential, options).ConfigureAwait(false); csm.ResetTimeToLiveIfNecessary(); return(result); } catch (ShardManagementException smme) { // If we hit a validation failure due to stale version of mapping, we will perform one more attempt. if (((options & ConnectionOptions.Validate) == ConnectionOptions.Validate) && smme.ErrorCategory == ShardManagementErrorCategory.Validation && smme.ErrorCode == ShardManagementErrorCode.MappingDoesNotExist) { // Assumption here is that this time the attempt should succeed since the cache entry // has already been either evicted, or updated based on latest data from the server. lookupMappingOnEx = true; cacheUpdatePolicyOnEx = CacheStoreMappingUpdatePolicy.OverwriteExisting; } else { // The error was not due to validation but something else e.g. // 1) Shard map does not exist // 2) Mapping could not be found. throw; } } catch (SqlException) { // We failed to connect. If we were trying to connect from an entry in cache and mapping expired in cache. if (csm != null && csm.HasTimeToLiveExpired()) { using (IdLock _idLock = new IdLock(csm.Mapping.StoreShard.Id)) { // Similar to DCL pattern, we need to refresh the mapping again to see if we still need to go to the store // to lookup the mapping after acquiring the shard lock. It might be the case that a fresh version has already // been obtained by some other thread. csm = this.Manager.Cache.LookupMappingByKey(this.ShardMap.StoreShardMap, sk); // Only go to store if the mapping is stale even after refresh. if (csm == null || csm.HasTimeToLiveExpired()) { // Refresh the mapping in cache. And try to open the connection after refresh. lookupMappingOnEx = true; cacheUpdatePolicyOnEx = CacheStoreMappingUpdatePolicy.UpdateTimeToLive; } else { sm = csm.Mapping; } } } else { // Either: // 1) The mapping is still within the TTL. No refresh. // 2) Mapping was not in cache, we originally did a lookup for mapping in GSM and even then could not connect. throw; } } if (lookupMappingOnEx) { sm = await this.LookupMappingForOpenConnectionForKeyAsync( sk, cacheUpdatePolicyOnEx, errorCategory).ConfigureAwait(false); } // One last attempt to open the connection after a cache refresh result = await this.ShardMap.OpenConnectionAsync( constructMapping(this.Manager, this.ShardMap, sm), connectionString, secureCredential, options).ConfigureAwait(false); // Reset TTL on successful connection. csm.ResetTimeToLiveIfNecessary(); return(result); }
/// <summary> /// Returns the proper ShardManagementException corresponding to given error code in /// <paramref name="result"/> for ShardMap operations. /// </summary> /// <param name="result">Operation result object.</param> /// <param name="shardMap">Shard map object.</param> /// <param name="shard">Shard object.</param> /// <param name="errorCategory">Error category to use for raised errors.</param> /// <param name="operationName">Operation being performed.</param> /// <param name="storedProcName">Stored procedure being executed.</param> /// <returns>ShardManagementException to be raised.</returns> internal static ShardManagementException OnShardMapErrorGlobal( IStoreResults result, IStoreShardMap shardMap, IStoreShard shard, ShardManagementErrorCategory errorCategory, string operationName, string storedProcName) { switch (result.Result) { case StoreResult.ShardMapDoesNotExist: return(new ShardManagementException( errorCategory, ShardManagementErrorCode.ShardMapDoesNotExist, Errors._Store_ShardMap_DoesNotExistGlobal, shardMap.Name, storedProcName, operationName, shard != null ? shard.Location.ToString() : "*")); case StoreResult.ShardExists: return(new ShardManagementException( errorCategory, ShardManagementErrorCode.ShardAlreadyExists, Errors._Store_Shard_AlreadyExistsGlobal, shard.Location, shardMap.Name, storedProcName, operationName)); case StoreResult.ShardLocationExists: return(new ShardManagementException( errorCategory, ShardManagementErrorCode.ShardLocationAlreadyExists, Errors._Store_Shard_LocationAlreadyExistsGlobal, shard.Location, shardMap.Name, storedProcName, operationName)); case StoreResult.ShardDoesNotExist: return(new ShardManagementException( errorCategory, ShardManagementErrorCode.ShardDoesNotExist, Errors._Store_Shard_DoesNotExistGlobal, shard.Location, shardMap.Name, storedProcName, operationName)); case StoreResult.ShardVersionMismatch: return(new ShardManagementException( errorCategory, ShardManagementErrorCode.ShardVersionMismatch, Errors._Store_Shard_VersionMismatchGlobal, shard.Location, shardMap.Name, storedProcName, operationName)); case StoreResult.ShardHasMappings: return(new ShardManagementException( errorCategory, ShardManagementErrorCode.ShardHasMappings, Errors._Store_Shard_HasMappingsGlobal, shard.Location, shardMap.Name, storedProcName, operationName)); case StoreResult.StoreVersionMismatch: case StoreResult.MissingParametersForStoredProcedure: default: return(StoreOperationErrorHandler.OnCommonErrorGlobal( result, operationName, storedProcName)); } }
/// <summary> /// Returns the proper ShardManagementException corresponding to given error code in /// <paramref name="result"/> for ShardMap operations. /// </summary> /// <param name="result">Operation result object.</param> /// <param name="shardMap">Shard map object.</param> /// <param name="shard">Shard object.</param> /// <param name="errorCategory">Error category to use for raised errors.</param> /// <param name="operationName">Operation being performed.</param> /// <param name="storedProcName">Stored procedure being executed.</param> /// <returns>ShardManagementException to be raised.</returns> internal static ShardManagementException OnRecoveryErrorGlobal( IStoreResults result, IStoreShardMap shardMap, IStoreShard shard, ShardManagementErrorCategory errorCategory, string operationName, string storedProcName) { switch (result.Result) { case StoreResult.ShardLocationExists: return new ShardManagementException( errorCategory, ShardManagementErrorCode.ShardLocationAlreadyExists, Errors._Store_Shard_LocationAlreadyExistsGlobal, shard.Location, shardMap.Name, storedProcName, operationName); case StoreResult.ShardMapExists: Debug.Assert(shardMap != null); return new ShardManagementException( errorCategory, ShardManagementErrorCode.ShardMapAlreadyExists, Errors._Store_ShardMap_AlreadyExistsGlobal, shardMap.Name, storedProcName, operationName); case StoreResult.StoreVersionMismatch: case StoreResult.MissingParametersForStoredProcedure: default: return StoreOperationErrorHandler.OnCommonErrorGlobal( result, operationName, storedProcName); } }
/// <summary> /// Returns the proper ShardManagementException corresponding to given error code in /// <paramref name="result"/> for ShardMap operations. /// </summary> /// <param name="result">Operation result object.</param> /// <param name="shardMap">Shard map object.</param> /// <param name="location">Location of operation.</param> /// <param name="errorCategory">Error category to use for raised errors.</param> /// <param name="operationName">Operation being performed.</param> /// <param name="storedProcName">Stored procedure being executed.</param> /// <returns>ShardManagementException to be raised.</returns> internal static ShardManagementException OnRecoveryErrorLocal( IStoreResults result, IStoreShardMap shardMap, ShardLocation location, ShardManagementErrorCategory errorCategory, string operationName, string storedProcName) { switch (result.Result) { case StoreResult.ShardMapDoesNotExist: return new ShardManagementException( errorCategory, ShardManagementErrorCode.ShardMapDoesNotExist, Errors._Store_ShardMap_DoesNotExistLocal, shardMap.Name, location, storedProcName, operationName); case StoreResult.StoreVersionMismatch: case StoreResult.MissingParametersForStoredProcedure: default: return StoreOperationErrorHandler.OnCommonErrorLocal( result, location, operationName, storedProcName); } }
/// <summary> /// Returns the proper ShardManagementException corresponding to given error code in /// <paramref name="result"/> for ShardMap operations. /// </summary> /// <param name="result">Operation result object.</param> /// <param name="shardMap">Shard map object.</param> /// <param name="shard">Shard object.</param> /// <param name="errorCategory">Error category to use for raised errors.</param> /// <param name="operationName">Operation being performed.</param> /// <param name="storedProcName">Stored procedure being executed.</param> /// <returns>ShardManagementException to be raised.</returns> internal static ShardManagementException OnShardMapErrorGlobal( IStoreResults result, IStoreShardMap shardMap, IStoreShard shard, ShardManagementErrorCategory errorCategory, string operationName, string storedProcName) { switch (result.Result) { case StoreResult.ShardMapDoesNotExist: return new ShardManagementException( errorCategory, ShardManagementErrorCode.ShardMapDoesNotExist, Errors._Store_ShardMap_DoesNotExistGlobal, shardMap.Name, storedProcName, operationName, shard != null ? shard.Location.ToString() : "*"); case StoreResult.ShardExists: return new ShardManagementException( errorCategory, ShardManagementErrorCode.ShardAlreadyExists, Errors._Store_Shard_AlreadyExistsGlobal, shard.Location, shardMap.Name, storedProcName, operationName); case StoreResult.ShardLocationExists: return new ShardManagementException( errorCategory, ShardManagementErrorCode.ShardLocationAlreadyExists, Errors._Store_Shard_LocationAlreadyExistsGlobal, shard.Location, shardMap.Name, storedProcName, operationName); case StoreResult.ShardDoesNotExist: return new ShardManagementException( errorCategory, ShardManagementErrorCode.ShardDoesNotExist, Errors._Store_Shard_DoesNotExistGlobal, shard.Location, shardMap.Name, storedProcName, operationName); case StoreResult.ShardVersionMismatch: return new ShardManagementException( errorCategory, ShardManagementErrorCode.ShardVersionMismatch, Errors._Store_Shard_VersionMismatchGlobal, shard.Location, shardMap.Name, storedProcName, operationName); case StoreResult.ShardHasMappings: return new ShardManagementException( errorCategory, ShardManagementErrorCode.ShardHasMappings, Errors._Store_Shard_HasMappingsGlobal, shard.Location, shardMap.Name, storedProcName, operationName); case StoreResult.StoreVersionMismatch: case StoreResult.MissingParametersForStoredProcedure: default: return StoreOperationErrorHandler.OnCommonErrorGlobal( result, operationName, storedProcName); } }
/// <summary> /// Constructs request for obtaining mapping from GSM based on given key. /// </summary> /// <param name="shardMapManager">Shard map manager.</param> /// <param name="operationName">Operation being executed.</param> /// <param name="shardMap">Local shard map.</param> /// <param name="mapping">Mapping whose Id will be used.</param> /// <param name="errorCategory">Error category.</param> /// <returns>The store operation.</returns> public virtual IStoreOperationGlobal CreateFindMappingByIdGlobalOperation( ShardMapManager shardMapManager, string operationName, IStoreShardMap shardMap, IStoreMapping mapping, ShardManagementErrorCategory errorCategory) { return new FindMappingByIdGlobalOperation( shardMapManager, operationName, shardMap, mapping, errorCategory); }
/// <summary> /// Constructs request to lock or unlock given mappings in GSM. /// </summary> /// <param name="shardMapManager">Shard map manager object.</param> /// <param name="operationName">Operation name, useful for diagnostics.</param> /// <param name="shardMap">Shard map to add.</param> /// <param name="mapping">Mapping to lock or unlock. Null means all mappings.</param> /// <param name="lockOwnerId">Lock owner.</param> /// <param name="lockOpType">Lock operation type.</param> /// <param name="errorCategory">Error category.</param> /// <returns>The store operation.</returns> public virtual IStoreOperationGlobal CreateLockOrUnLockMappingsGlobalOperation( ShardMapManager shardMapManager, string operationName, IStoreShardMap shardMap, IStoreMapping mapping, Guid lockOwnerId, LockOwnerIdOpType lockOpType, ShardManagementErrorCategory errorCategory) { return new LockOrUnLockMappingsGlobalOperation( shardMapManager, operationName, shardMap, mapping, lockOwnerId, lockOpType, errorCategory); }
/// <summary> /// Initializes a new instance with a specified error message and a reference to the inner exception /// that is the cause of this exception. /// </summary> /// <param name="category">Category of error.</param> /// <param name="code">Error code.</param> /// <param name="message">A message that describes the error</param> /// <param name="inner">The exception that is the cause of the current exception</param> internal ShardManagementException(ShardManagementErrorCategory category, ShardManagementErrorCode code, string message, Exception inner) : base(message, inner) { this.ErrorCategory = category; this.ErrorCode = code; }
/// <summary> /// Looks up the key value and returns the corresponding mapping. /// </summary> /// <typeparam name="TMapping">Mapping type.</typeparam> /// <typeparam name="TKey">Key type.</typeparam> /// <param name="key">Input key value.</param> /// <param name="lookupOptions">Whether to use cache and/or storage for lookups.</param> /// <param name="constructMapping">Delegate to construct a mapping object.</param> /// <param name="errorCategory">Category under which errors must be thrown.</param> /// <returns>Mapping that contains the key value.</returns> protected TMapping Lookup <TMapping, TKey>( TKey key, LookupOptions lookupOptions, Func <ShardMapManager, ShardMap, IStoreMapping, TMapping> constructMapping, ShardManagementErrorCategory errorCategory) where TMapping : class, IShardProvider { ShardKey sk = new ShardKey(ShardKey.ShardKeyTypeFromType(typeof(TKey)), key); // Try to lookup in cache. Note the interation with cache removal later in this method. bool tryLookupInCache = lookupOptions.HasFlag(LookupOptions.LookupInCache); if (tryLookupInCache) { ICacheStoreMapping cachedMapping = this.Manager.Cache.LookupMappingByKey(this.ShardMap.StoreShardMap, sk); if (cachedMapping != null) { return(constructMapping(this.Manager, this.ShardMap, cachedMapping.Mapping)); } } // Cache-miss (or didn't use cache), find mapping for given key in GSM. if (lookupOptions.HasFlag(LookupOptions.LookupInStore)) { IStoreResults gsmResult; Stopwatch stopwatch = Stopwatch.StartNew(); using (IStoreOperationGlobal op = this.Manager.StoreOperationFactory.CreateFindMappingByKeyGlobalOperation( this.Manager, "Lookup", this.ShardMap.StoreShardMap, sk, CacheStoreMappingUpdatePolicy.OverwriteExisting, errorCategory, true, false)) { gsmResult = op.Do(); } stopwatch.Stop(); Tracer.TraceVerbose( TraceSourceConstants.ComponentNames.BaseShardMapper, "Lookup", "Lookup key from GSM complete; Key type : {0}; Result: {1}; Duration: {2}", typeof(TKey), gsmResult.Result, stopwatch.Elapsed); // If mapping was found, return it. if (gsmResult.Result != StoreResult.MappingNotFoundForKey) { return(gsmResult.StoreMappings.Select(sm => constructMapping(this.Manager, this.ShardMap, sm)).Single()); } // If we could not locate the mapping, then we might need to update the cache to remove it. // // Only do this if we didn't already try to return the mapping from the cache (since, if it was found, // we would have already returned it earlier). if (!tryLookupInCache) { ICacheStoreMapping cachedMapping = this.Manager.Cache.LookupMappingByKey(this.ShardMap.StoreShardMap, sk); if (cachedMapping != null) { this.Manager.Cache.DeleteMapping(cachedMapping.Mapping); } } } // Mapping not found - return null return(null); }
/// <summary> /// Initializes a new instance with a specified formatted error message and a reference to the /// inner exception that is the cause of this exception. /// </summary> /// <param name="category">Category of error.</param> /// <param name="code">Error code.</param> /// <param name="format">The format message that describes the error</param> /// <param name="inner">The exception that is the cause of the current exception</param> /// <param name="args">The arguments to the format string</param> internal ShardManagementException(ShardManagementErrorCategory category, ShardManagementErrorCode code, string format, Exception inner, params object[] args) : base(string.Format(CultureInfo.InvariantCulture, format, args), inner) { this.ErrorCategory = category; this.ErrorCode = code; }
/// <summary> /// Sets the stub of StoreOperationFactory.CreateLockOrUnLockMappingsGlobalOperation(ShardMapManager shardMapManager, String operationName, IStoreShardMap shardMap, IStoreMapping mapping, Guid lockOwnerId, LockOwnerIdOpType lockOpType, ShardManagementErrorCategory errorCategory) /// </summary> public override IStoreOperationGlobal CreateLockOrUnLockMappingsGlobalOperation(ShardMapManager shardMapManager, string operationName, IStoreShardMap shardMap, IStoreMapping mapping, Guid lockOwnerId, LockOwnerIdOpType lockOpType, ShardManagementErrorCategory errorCategory) { Func<ShardMapManager, string, IStoreShardMap, IStoreMapping, Guid, LockOwnerIdOpType, ShardManagementErrorCategory, IStoreOperationGlobal> func1 = this.CreateLockOrUnLockMappingsGlobalOperationShardMapManagerStringIStoreShardMapIStoreMappingGuidLockOwnerIdOpTypeShardManagementErrorCategory; if (func1 != null) return func1(shardMapManager, operationName, shardMap, mapping, lockOwnerId, lockOpType, errorCategory); if (this.___callBase) return base.CreateLockOrUnLockMappingsGlobalOperation(shardMapManager, operationName, shardMap, mapping, lockOwnerId, lockOpType, errorCategory); return this.InstanceBehavior.Result<StubStoreOperationFactory, IStoreOperationGlobal>(this, "CreateLockOrUnLockMappingsGlobalOperation"); }
/// <summary> /// Returns the proper ShardManagementException corresponding to given error code in /// <paramref name="result"/> for ShardMapper operations. /// </summary> /// <param name="result">Operation result object.</param> /// <param name="shardMap">Shard map object.</param> /// <param name="shard">Shard object.</param> /// <param name="errorCategory">Error category to use for raised errors.</param> /// <param name="operationName">Operation being performed.</param> /// <param name="storedProcName">Stored procedure being executed.</param> /// <returns>ShardManagementException to be raised.</returns> internal static ShardManagementException OnShardMapperErrorGlobal( IStoreResults result, IStoreShardMap shardMap, IStoreShard shard, ShardManagementErrorCategory errorCategory, string operationName, string storedProcName) { switch (result.Result) { case StoreResult.ShardMapDoesNotExist: return new ShardManagementException( errorCategory, ShardManagementErrorCode.ShardMapDoesNotExist, Errors._Store_ShardMap_DoesNotExistGlobal, shardMap.Name, storedProcName, operationName, shard != null ? shard.Location.ToString() : "*"); case StoreResult.ShardDoesNotExist: return new ShardManagementException( errorCategory, ShardManagementErrorCode.ShardDoesNotExist, Errors._Store_Shard_DoesNotExistGlobal, shard.Location, shardMap.Name, storedProcName, operationName); case StoreResult.ShardVersionMismatch: return new ShardManagementException( errorCategory, ShardManagementErrorCode.ShardVersionMismatch, Errors._Store_Shard_VersionMismatchGlobal, shard.Location, shardMap.Name, storedProcName, operationName); case StoreResult.MappingDoesNotExist: return new ShardManagementException( errorCategory, ShardManagementErrorCode.MappingDoesNotExist, Errors._Store_ShardMapper_MappingDoesNotExistGlobal, shard.Location, shardMap.Name, storedProcName, operationName); case StoreResult.MappingRangeAlreadyMapped: return new ShardManagementException( errorCategory, ShardManagementErrorCode.MappingRangeAlreadyMapped, Errors._Store_ShardMapper_MappingPointOrRangeAlreadyMapped, shard.Location, shardMap.Name, "Range", storedProcName, operationName); case StoreResult.MappingPointAlreadyMapped: return new ShardManagementException( errorCategory, ShardManagementErrorCode.MappingPointAlreadyMapped, Errors._Store_ShardMapper_MappingPointOrRangeAlreadyMapped, shard.Location, shardMap.Name, "Point", storedProcName, operationName); case StoreResult.MappingNotFoundForKey: Debug.Fail("MappingNotFoundForKey should not be raised during SqlOperation."); return new ShardManagementException( errorCategory, ShardManagementErrorCode.MappingNotFoundForKey, Errors._Store_ShardMapper_MappingNotFoundForKeyGlobal, shardMap.Name, storedProcName, operationName); case StoreResult.MappingIsAlreadyLocked: return new ShardManagementException( errorCategory, ShardManagementErrorCode.MappingIsAlreadyLocked, Errors._Store_ShardMapper_LockMappingAlreadyLocked, shard.Location, shardMap.Name, storedProcName, operationName); case StoreResult.MappingLockOwnerIdDoesNotMatch: return new ShardManagementException( errorCategory, ShardManagementErrorCode.MappingLockOwnerIdDoesNotMatch, Errors._Store_ShardMapper_LockOwnerDoesNotMatch, shard.Location, shardMap.Name, storedProcName, operationName); case StoreResult.MappingIsNotOffline: return new ShardManagementException( errorCategory, ShardManagementErrorCode.MappingIsNotOffline, Errors._Store_ShardMapper_MappingIsNotOffline, shard.Location, shardMap.Name, storedProcName, operationName); case StoreResult.StoreVersionMismatch: case StoreResult.MissingParametersForStoredProcedure: default: return StoreOperationErrorHandler.OnCommonErrorGlobal( result, operationName, storedProcName); } }
/// <summary> /// Sets the stub of StoreOperationFactory.CreateGetMappingsByRangeGlobalOperation(ShardMapManager shardMapManager, String operationName, IStoreShardMap shardMap, IStoreShard shard, ShardRange range, ShardManagementErrorCategory errorCategory, Boolean cacheResults, Boolean ignoreFailure) /// </summary> public override IStoreOperationGlobal CreateGetMappingsByRangeGlobalOperation(ShardMapManager shardMapManager, string operationName, IStoreShardMap shardMap, IStoreShard shard, ShardRange range, ShardManagementErrorCategory errorCategory, bool cacheResults, bool ignoreFailure) { Func<ShardMapManager, string, IStoreShardMap, IStoreShard, ShardRange, ShardManagementErrorCategory, bool, bool, IStoreOperationGlobal> func1 = this.CreateGetMappingsByRangeGlobalOperationShardMapManagerStringIStoreShardMapIStoreShardShardRangeShardManagementErrorCategoryBooleanBoolean; if (func1 != null) return func1(shardMapManager, operationName, shardMap, shard, range, errorCategory, cacheResults, ignoreFailure); if (this.___callBase) return base.CreateGetMappingsByRangeGlobalOperation(shardMapManager, operationName, shardMap, shard, range, errorCategory, cacheResults, ignoreFailure); return this.InstanceBehavior.Result<StubStoreOperationFactory, IStoreOperationGlobal>(this, "CreateGetMappingsByRangeGlobalOperation"); }
/// <summary> /// Sets the stub of StoreOperationFactory.CreateFindMappingByIdGlobalOperation(ShardMapManager shardMapManager, String operationName, IStoreShardMap shardMap, IStoreMapping mapping, ShardManagementErrorCategory errorCategory) /// </summary> public override IStoreOperationGlobal CreateFindMappingByIdGlobalOperation(ShardMapManager shardMapManager, string operationName, IStoreShardMap shardMap, IStoreMapping mapping, ShardManagementErrorCategory errorCategory) { Func<ShardMapManager, string, IStoreShardMap, IStoreMapping, ShardManagementErrorCategory, IStoreOperationGlobal> func1 = this.CreateFindMappingByIdGlobalOperationShardMapManagerStringIStoreShardMapIStoreMappingShardManagementErrorCategory; if (func1 != null) return func1(shardMapManager, operationName, shardMap, mapping, errorCategory); if (this.___callBase) return base.CreateFindMappingByIdGlobalOperation(shardMapManager, operationName, shardMap, mapping, errorCategory); return this.InstanceBehavior.Result<StubStoreOperationFactory, IStoreOperationGlobal>(this, "CreateFindMappingByIdGlobalOperation"); }
internal void LockOrUnlockMappings <TMapping>(TMapping mapping, Guid lockOwnerId, LockOwnerIdOpType lockOwnerIdOpType, ShardManagementErrorCategory errorCategory) where TMapping : class, IShardProvider, IMappingInfoProvider { string operationName = lockOwnerIdOpType == LockOwnerIdOpType.Lock ? "Lock" : "UnLock"; if (lockOwnerIdOpType != LockOwnerIdOpType.UnlockAllMappingsForId && lockOwnerIdOpType != LockOwnerIdOpType.UnlockAllMappings) { this.EnsureMappingBelongsToShardMap <TMapping>(mapping, operationName, "mapping"); if (lockOwnerIdOpType == LockOwnerIdOpType.Lock && lockOwnerId == MappingLockToken.ForceUnlock.LockOwnerId) { throw new ArgumentException( StringUtils.FormatInvariant( Errors._ShardMapping_LockIdNotSupported, mapping.ShardInfo.Location, this.ShardMap.Name, lockOwnerId), "lockOwnerId"); } } else { Debug.Assert(mapping == null); } using (IStoreOperationGlobal op = this.Manager.StoreOperationFactory.CreateLockOrUnLockMappingsGlobalOperation( this.Manager, operationName, this.ShardMap.StoreShardMap, mapping != null ? mapping.StoreMapping : null, lockOwnerId, lockOwnerIdOpType, errorCategory)) { op.Do(); } }
/// <summary> /// Returns the proper ShardManagementException corresponding to given error code in /// <paramref name="result"/> for ShardMap operations. /// </summary> /// <param name="result">Operation result object.</param> /// <param name="shardMap">Shard map object.</param> /// <param name="location">Location of LSM operation.</param> /// <param name="errorCategory">Error category to use for raised errors.</param> /// <param name="operationName">Operation being performed.</param> /// <param name="storedProcName">Stored procedure being executed.</param> /// <returns>ShardManagementException to be raised.</returns> internal static ShardManagementException OnShardMapErrorLocal( IStoreResults result, IStoreShardMap shardMap, ShardLocation location, ShardManagementErrorCategory errorCategory, string operationName, string storedProcName) { switch (result.Result) { case StoreResult.UnableToKillSessions: return new ShardManagementException( errorCategory, ShardManagementErrorCode.MappingsKillConnectionFailure, Errors._Store_ShardMapper_UnableToKillSessions, location, shardMap.Name, operationName, storedProcName, location); case StoreResult.StoreVersionMismatch: case StoreResult.MissingParametersForStoredProcedure: case StoreResult.ShardDoesNotExist: // ShardDoesNotExist on local shard map can only occur in Recovery scenario. // For normal UpdateShard operation, we will get this error from GSM operation first. return new ShardManagementException( ShardManagementErrorCategory.Recovery, ShardManagementErrorCode.ShardDoesNotExist, Errors._Store_Validate_ShardDoesNotExist, location, shardMap.Name, operationName, storedProcName); default: return StoreOperationErrorHandler.OnCommonErrorLocal( result, location, operationName, storedProcName); } }
/// <summary> /// Creates request to add shard to given shard map. /// </summary> /// <param name="shardMapManager">Shard map manager object.</param> /// <param name="operationId">Operation id.</param> /// <param name="undoStartState">State from which Undo operation starts.</param> /// <param name="operationCode">Store operation code.</param> /// <param name="shardMap">Shard map for which to update mapping.</param> /// <param name="mappingSource">Mapping to update.</param> /// <param name="mappingTarget">Updated mapping.</param> /// <param name="patternForKill">Pattern for kill commands.</param> /// <param name="lockOwnerId">Id of lock owner.</param> /// <param name="originalShardVersionRemoves">Original shard version for removes.</param> /// <param name="originalShardVersionAdds">Original shard version for adds.</param> internal UpdateMappingOperation( ShardMapManager shardMapManager, Guid operationId, StoreOperationState undoStartState, StoreOperationCode operationCode, IStoreShardMap shardMap, IStoreMapping mappingSource, IStoreMapping mappingTarget, string patternForKill, Guid lockOwnerId, Guid originalShardVersionRemoves, Guid originalShardVersionAdds) : base( shardMapManager, operationId, undoStartState, operationCode, originalShardVersionRemoves, originalShardVersionAdds) { _shardMap = shardMap; _mappingSource = mappingSource; _mappingTarget = mappingTarget; _lockOwnerId = lockOwnerId; _errorCategory = (operationCode == StoreOperationCode.UpdateRangeMapping || operationCode == StoreOperationCode.UpdateRangeMappingWithOffline) ? ShardManagementErrorCategory.RangeShardMap : ShardManagementErrorCategory.ListShardMap; _updateLocation = _mappingSource.StoreShard.Id != _mappingTarget.StoreShard.Id; _fromOnlineToOffline = operationCode == StoreOperationCode.UpdatePointMappingWithOffline || operationCode == StoreOperationCode.UpdateRangeMappingWithOffline; _patternForKill = patternForKill; }
/// <summary> /// Returns the proper ShardManagementException corresponding to given error code in /// <paramref name="result"/> for ShardMapper operations. /// </summary> /// <param name="result">Operation result object.</param> /// <param name="shardMap">Shard map object.</param> /// <param name="shard">Shard object.</param> /// <param name="errorCategory">Error category to use for raised errors.</param> /// <param name="operationName">Operation being performed.</param> /// <param name="storedProcName">Stored procedure being executed.</param> /// <returns>ShardManagementException to be raised.</returns> internal static ShardManagementException OnShardMapperErrorGlobal( IStoreResults result, IStoreShardMap shardMap, IStoreShard shard, ShardManagementErrorCategory errorCategory, string operationName, string storedProcName) { switch (result.Result) { case StoreResult.ShardMapDoesNotExist: return(new ShardManagementException( errorCategory, ShardManagementErrorCode.ShardMapDoesNotExist, Errors._Store_ShardMap_DoesNotExistGlobal, shardMap.Name, storedProcName, operationName, shard != null ? shard.Location.ToString() : "*")); case StoreResult.ShardDoesNotExist: return(new ShardManagementException( errorCategory, ShardManagementErrorCode.ShardDoesNotExist, Errors._Store_Shard_DoesNotExistGlobal, shard.Location, shardMap.Name, storedProcName, operationName)); case StoreResult.ShardVersionMismatch: return(new ShardManagementException( errorCategory, ShardManagementErrorCode.ShardVersionMismatch, Errors._Store_Shard_VersionMismatchGlobal, shard.Location, shardMap.Name, storedProcName, operationName)); case StoreResult.MappingDoesNotExist: return(new ShardManagementException( errorCategory, ShardManagementErrorCode.MappingDoesNotExist, Errors._Store_ShardMapper_MappingDoesNotExistGlobal, shard.Location, shardMap.Name, storedProcName, operationName)); case StoreResult.MappingRangeAlreadyMapped: return(new ShardManagementException( errorCategory, ShardManagementErrorCode.MappingRangeAlreadyMapped, Errors._Store_ShardMapper_MappingPointOrRangeAlreadyMapped, shard.Location, shardMap.Name, "Range", storedProcName, operationName)); case StoreResult.MappingPointAlreadyMapped: return(new ShardManagementException( errorCategory, ShardManagementErrorCode.MappingPointAlreadyMapped, Errors._Store_ShardMapper_MappingPointOrRangeAlreadyMapped, shard.Location, shardMap.Name, "Point", storedProcName, operationName)); case StoreResult.MappingNotFoundForKey: Debug.Fail("MappingNotFoundForKey should not be raised during SqlOperation."); return(new ShardManagementException( errorCategory, ShardManagementErrorCode.MappingNotFoundForKey, Errors._Store_ShardMapper_MappingNotFoundForKeyGlobal, shardMap.Name, storedProcName, operationName)); case StoreResult.MappingIsAlreadyLocked: return(new ShardManagementException( errorCategory, ShardManagementErrorCode.MappingIsAlreadyLocked, Errors._Store_ShardMapper_LockMappingAlreadyLocked, shard.Location, shardMap.Name, storedProcName, operationName)); case StoreResult.MappingLockOwnerIdDoesNotMatch: return(new ShardManagementException( errorCategory, ShardManagementErrorCode.MappingLockOwnerIdDoesNotMatch, Errors._Store_ShardMapper_LockOwnerDoesNotMatch, shard.Location, shardMap.Name, storedProcName, operationName)); case StoreResult.MappingIsNotOffline: return(new ShardManagementException( errorCategory, ShardManagementErrorCode.MappingIsNotOffline, Errors._Store_ShardMapper_MappingIsNotOffline, shard.Location, shardMap.Name, storedProcName, operationName)); case StoreResult.StoreVersionMismatch: case StoreResult.MissingParametersForStoredProcedure: default: return(StoreOperationErrorHandler.OnCommonErrorGlobal( result, operationName, storedProcName)); } }
/// <summary> /// Given a key value, obtains a SqlConnection to the shard in the mapping /// that contains the key value. /// </summary> /// <typeparam name="TMapping">Mapping type.</typeparam> /// <typeparam name="TKey">Key type.</typeparam> /// <param name="key">Input key value.</param> /// <param name="constructMapping">Delegate to construct a mapping object.</param> /// <param name="errorCategory">Error category.</param> /// <param name="connectionInfo"> /// Connection info with credential information, the DataSource and Database are /// obtained from the results of the lookup operation for key. /// </param> /// <param name="options">Options for validation operations to perform on opened connection.</param> /// <returns>An opened SqlConnection.</returns> protected SqlConnection OpenConnectionForKey <TMapping, TKey>( TKey key, Func <ShardMapManager, ShardMap, IStoreMapping, TMapping> constructMapping, ShardManagementErrorCategory errorCategory, SqlConnectionInfo connectionInfo, ConnectionOptions options = ConnectionOptions.Validate) where TMapping : class, IShardProvider { ShardKey sk = new ShardKey(ShardKey.ShardKeyTypeFromType(typeof(TKey)), key); // Try to find the mapping within the cache. ICacheStoreMapping csm = this.Manager.Cache.LookupMappingByKey(this.ShardMap.StoreShardMap, sk); IStoreMapping sm; if (csm != null) { sm = csm.Mapping; } else { sm = this.LookupMappingForOpenConnectionForKey( sk, CacheStoreMappingUpdatePolicy.OverwriteExisting, errorCategory); } SqlConnection result; try { // Initially attempt to connect based on lookup results from either cache or GSM. result = this.ShardMap.OpenConnection( constructMapping(this.Manager, this.ShardMap, sm), connectionInfo, options); // Reset TTL on successful connection. if (csm != null && csm.TimeToLiveMilliseconds > 0) { csm.ResetTimeToLive(); } this.Manager.Cache.IncrementPerformanceCounter(this.ShardMap.StoreShardMap, PerformanceCounterName.DdrOperationsPerSec); return(result); } catch (ShardManagementException smme) { // If we hit a validation failure due to stale version of mapping, we will perform one more attempt. if (((options & ConnectionOptions.Validate) == ConnectionOptions.Validate) && smme.ErrorCategory == ShardManagementErrorCategory.Validation && smme.ErrorCode == ShardManagementErrorCode.MappingDoesNotExist) { // Assumption here is that this time the attempt should succeed since the cache entry // has already been either evicted, or updated based on latest data from the server. sm = this.LookupMappingForOpenConnectionForKey( sk, CacheStoreMappingUpdatePolicy.OverwriteExisting, errorCategory); result = this.ShardMap.OpenConnection( constructMapping(this.Manager, this.ShardMap, sm), connectionInfo, options); this.Manager.Cache.IncrementPerformanceCounter(this.ShardMap.StoreShardMap, PerformanceCounterName.DdrOperationsPerSec); return(result); } else { // The error was not due to validation but something else e.g. // 1) Shard map does not exist // 2) Mapping could not be found. throw; } } catch (SqlException) { // We failed to connect. If we were trying to connect from an entry in cache and mapping expired in cache. if (csm != null && TimerUtils.ElapsedMillisecondsSince(csm.CreationTime) >= csm.TimeToLiveMilliseconds) { using (IdLock _idLock = new IdLock(csm.Mapping.StoreShard.Id)) { // Similar to DCL pattern, we need to refresh the mapping again to see if we still need to go to the store // to lookup the mapping after acquiring the shard lock. It might be the case that a fresh version has already // been obtained by some other thread. csm = this.Manager.Cache.LookupMappingByKey(this.ShardMap.StoreShardMap, sk); // Only go to store if the mapping is stale even after refresh. if (csm == null || TimerUtils.ElapsedMillisecondsSince(csm.CreationTime) >= csm.TimeToLiveMilliseconds) { // Refresh the mapping in cache. And try to open the connection after refresh. sm = this.LookupMappingForOpenConnectionForKey( sk, CacheStoreMappingUpdatePolicy.UpdateTimeToLive, errorCategory); } else { sm = csm.Mapping; } } result = this.ShardMap.OpenConnection( constructMapping(this.Manager, this.ShardMap, sm), connectionInfo, options); // Reset TTL on successful connection. if (csm != null && csm.TimeToLiveMilliseconds > 0) { csm.ResetTimeToLive(); } this.Manager.Cache.IncrementPerformanceCounter(this.ShardMap.StoreShardMap, PerformanceCounterName.DdrOperationsPerSec); return(result); } else { // Either: // 1) The mapping is still within the TTL. No refresh. // 2) Mapping was not in cache, we originally did a lookup for mapping in GSM and even then could not connect. throw; } } }
/// <summary> /// Constructs request for obtaining mapping from GSM based on given key. /// </summary> /// <param name="shardMapManager">Shard map manager.</param> /// <param name="operationName">Operation being executed.</param> /// <param name="shardMap">Local shard map.</param> /// <param name="key">Key for lookup operation.</param> /// <param name="policy">Policy for cache update.</param> /// <param name="errorCategory">Error category.</param> /// <param name="cacheResults">Whether to cache the results of the operation.</param> /// <param name="ignoreFailure">Ignore shard map not found error.</param> /// <returns>The store operation.</returns> public virtual IStoreOperationGlobal CreateFindMappingByKeyGlobalOperation( ShardMapManager shardMapManager, string operationName, IStoreShardMap shardMap, ShardKey key, CacheStoreMappingUpdatePolicy policy, ShardManagementErrorCategory errorCategory, bool cacheResults, bool ignoreFailure) { return new FindMappingByKeyGlobalOperation( shardMapManager, operationName, shardMap, key, policy, errorCategory, cacheResults, ignoreFailure); }