/// <summary>
        /// Add or update a mapping in cache.
        /// </summary>
        /// <param name="sm">Storage mapping object.</param>
        /// <param name="policy">Policy to use for preexisting cache entries during update.</param>
        internal override void AddOrUpdate(IStoreMapping sm, CacheStoreMappingUpdatePolicy policy)
        {
            ShardKey min = ShardKey.FromRawValue(this.KeyType, sm.MinValue);

            // Make range out of mapping key ranges.
            ShardRange range = new ShardRange(
                min,
                ShardKey.FromRawValue(this.KeyType, sm.MaxValue));

            CacheMapping cm;
            ICacheStoreMapping csm;

            IStoreMapping smDummy;

            // We need to update TTL and update entry if:
            // a) We are in update TTL mode
            // b) Mapping exists and same as the one we already have 
            // c) Entry is beyond the TTL limit
            if (policy == CacheStoreMappingUpdatePolicy.UpdateTimeToLive &&
                (csm = this.LookupByKey(min, out smDummy)) != null &&
                csm.Mapping.Id == sm.Id /*&&
                TimerUtils.ElapsedMillisecondsSince(csm.CreationTime) >= csm.TimeToLiveMilliseconds */)
            {
                cm = new CacheMapping(sm, CacheMapper.CalculateNewTimeToLiveMilliseconds(csm));
            }
            else
            {
                cm = new CacheMapping(sm);
            }

            this.Remove(sm);

            // Add the entry to lookup table by Range.
            _mappingsByRange.Add(range, cm);
        }
 /// <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>
 /// Instantiates a new instance of range mapping comparison result.
 /// </summary>
 /// <param name="ssm">Store representation of shard map.</param>
 /// <param name="range">Range being considered.</param>
 /// <param name="mappingLocation">Location of mapping.</param>
 /// <param name="gsmMapping">Storage representation of GSM mapping.</param>
 /// <param name="lsmMapping">Storange representation of LSM mapping.</param>
 internal MappingComparisonResult(
     IStoreShardMap ssm,
     ShardRange range,
     MappingLocation mappingLocation,
     IStoreMapping gsmMapping,
     IStoreMapping lsmMapping)
 {
     this.ShardMap = ssm;
     this.Range = range;
     this.MappingLocation = mappingLocation;
     this.ShardMapManagerMapping = gsmMapping;
     this.ShardMapping = lsmMapping;
 }
 /// <summary>
 /// Helper function to advance mapping iterators.
 /// </summary>
 /// <param name="iterator">The iterator to advance.</param>
 /// <param name="keyType">The data type of the map key.</param>
 /// <param name="nextMapping">Output value that will contain next mapping.</param>
 /// <param name="nextRange">Output value that will contain next range.</param>
 /// <param name="nextMinKey">Output value that will contain next min key.</param>
 private static void MoveToNextMapping(
     IEnumerator <IStoreMapping> iterator,
     ShardKeyType keyType,
     out IStoreMapping nextMapping,
     out ShardRange nextRange,
     out ShardKey nextMinKey)
 {
     nextMapping = iterator.MoveNext() ? iterator.Current : null;
     nextRange   = nextMapping != null ? new ShardRange(
         ShardKey.FromRawValue(keyType, nextMapping.MinValue),
         ShardKey.FromRawValue(keyType, nextMapping.MaxValue)) : null;
     nextMinKey = nextRange != null ? nextRange.Low : null;
 }
Example #5
0
 /// <summary>
 /// Instantiates a new instance of range mapping comparison result.
 /// </summary>
 /// <param name="ssm">Store representation of shard map.</param>
 /// <param name="range">Range being considered.</param>
 /// <param name="mappingLocation">Location of mapping.</param>
 /// <param name="gsmMapping">Storage representation of GSM mapping.</param>
 /// <param name="lsmMapping">Storange representation of LSM mapping.</param>
 internal MappingComparisonResult(
     IStoreShardMap ssm,
     ShardRange range,
     MappingLocation mappingLocation,
     IStoreMapping gsmMapping,
     IStoreMapping lsmMapping)
 {
     this.ShardMap               = ssm;
     this.Range                  = range;
     this.MappingLocation        = mappingLocation;
     this.ShardMapManagerMapping = gsmMapping;
     this.ShardMapping           = lsmMapping;
 }
        /// <summary>
        /// Constructs request for obtaining all the shard maps and shards from an LSM.
        /// </summary>
        /// <param name="shardMapManager">Shard map manager.</param>
        /// <param name="location">Location of the LSM.</param>
        /// <param name="operationName">Operation name.</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="ignoreFailure">Ignore shard map not found error.</param>
        internal GetMappingsByRangeLocalOperation(
            ShardMapManager shardMapManager,
            ShardLocation location,
            string operationName,
            IStoreShardMap shardMap,
            IStoreShard shard,
            ShardRange range,
            bool ignoreFailure) :
            base(shardMapManager.Credentials, shardMapManager.RetryPolicy, location, operationName)
        {
            Debug.Assert(shard != null);

            _shardMap = shardMap;
            _shard = shard;
            _range = range;
            _ignoreFailure = ignoreFailure;
        }
Example #7
0
        public void CheckValidity()
        {
            if (!ShardRange.IsValid())
            {
                throw new InvalidConfigurationException("Shard range is invalid.");
            }

            if (ShardRange.Min < 0)
            {
                throw new InvalidConfigurationException("Shard range minimum is below zero.");
            }

            if (ShardRange.Max > TotalShards)
            {
                throw new InvalidConfigurationException("Shard range max is above total shard count.");
            }

            if (string.IsNullOrWhiteSpace(Token))
            {
                throw new InvalidConfigurationException("Configuration contains no token.");
            }
        }
        /// <summary>
        /// Finds all mappings to be purged based on the given input ranges.
        /// </summary>
        /// <param name="ts">LSM transaction scope.</param>
        /// <returns>Mappings which are to be removed.</returns>
        private IEnumerable<IStoreMapping> GetMappingsToPurge(IStoreTransactionScope ts)
        {
            IEnumerable<IStoreMapping> lsmMappings = null;

            IStoreResults result;

            if (_rangesToRemove == null)
            {
                // If no ranges are specified, get all the mappings for the shard.
                result = ts.ExecuteOperation(
                    StoreOperationRequestBuilder.SpGetAllShardMappingsLocal,
                    StoreOperationRequestBuilder.GetAllShardMappingsLocal(_shardMap, _shard, null));

                if (result.Result != StoreResult.Success)
                {
                    // Possible errors are:
                    // StoreResult.ShardMapDoesNotExist
                    // StoreResult.StoreVersionMismatch
                    // StoreResult.MissingParametersForStoredProcedure
                    throw StoreOperationErrorHandler.OnRecoveryErrorLocal(
                        result,
                        _shardMap,
                        this.Location,
                        ShardManagementErrorCategory.Recovery,
                        this.OperationName,
                        StoreOperationRequestBuilder.SpGetAllShardMappingsLocal);
                }

                lsmMappings = result.StoreMappings;
            }
            else
            {
                // If any ranges are specified, only delete intersected ranges.
                IDictionary<ShardRange, IStoreMapping> mappingsToPurge = new Dictionary<ShardRange, IStoreMapping>();

                foreach (ShardRange range in _rangesToRemove)
                {
                    switch (_shardMap.MapType)
                    {
                        case ShardMapType.Range:
                            result = ts.ExecuteOperation(
                                StoreOperationRequestBuilder.SpGetAllShardMappingsLocal,
                                StoreOperationRequestBuilder.GetAllShardMappingsLocal(
                                    _shardMap,
                                    _shard,
                                    range));
                            break;

                        default:
                            Debug.Assert(_shardMap.MapType == ShardMapType.List);
                            result = ts.ExecuteOperation(
                                StoreOperationRequestBuilder.SpFindShardMappingByKeyLocal,
                                StoreOperationRequestBuilder.FindShardMappingByKeyLocal(
                                    _shardMap,
                                    ShardKey.FromRawValue(_shardMap.KeyType, range.Low.RawValue)));
                            break;
                    }

                    if (result.Result != StoreResult.Success)
                    {
                        if (result.Result != StoreResult.MappingNotFoundForKey)
                        {
                            // Possible errors are:
                            // StoreResult.ShardMapDoesNotExist
                            // StoreResult.StoreVersionMismatch
                            // StoreResult.MissingParametersForStoredProcedure
                            throw StoreOperationErrorHandler.OnRecoveryErrorLocal(
                                result,
                                _shardMap,
                                this.Location,
                                ShardManagementErrorCategory.Recovery,
                                this.OperationName,
                                _shardMap.MapType == ShardMapType.Range ?
                                StoreOperationRequestBuilder.SpGetAllShardMappingsLocal :
                                StoreOperationRequestBuilder.SpFindShardMappingByKeyLocal);
                        }
                        else
                        {
                            // No intersections being found is fine. Skip to the next mapping.
                            Debug.Assert(_shardMap.MapType == ShardMapType.List);
                        }
                    }
                    else
                    {
                        foreach (IStoreMapping mapping in result.StoreMappings)
                        {
                            ShardRange intersectedRange = new ShardRange(
                                ShardKey.FromRawValue(_shardMap.KeyType, mapping.MinValue),
                                ShardKey.FromRawValue(_shardMap.KeyType, mapping.MaxValue));

                            mappingsToPurge[intersectedRange] = mapping;
                        }
                    }
                }

                lsmMappings = mappingsToPurge.Values;
            }

            return lsmMappings;
        }
 /// <summary>
 /// Constructs request for obtaining all the shard maps and shards from an LSM.
 /// </summary>
 /// <param name="shardMapManager">Shard map manager.</param>
 /// <param name="location">Location of the LSM.</param>
 /// <param name="operationName">Operation name.</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="ignoreFailure">Ignore shard map not found error.</param>
 public virtual IStoreOperationLocal CreateGetMappingsByRangeLocalOperation(
     ShardMapManager shardMapManager,
     ShardLocation location,
     string operationName,
     IStoreShardMap shardMap,
     IStoreShard shard,
     ShardRange range,
     bool ignoreFailure)
 {
     return new GetMappingsByRangeLocalOperation(
         shardMapManager,
         location,
         operationName,
         shardMap,
         shard,
         range,
         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>
 /// Request to get all shard mappings from LSM for a particular shard map
 /// and optional shard and range.
 /// </summary>
 /// <param name="shardMap">Shard map whose mappings are being requested.</param>
 /// <param name="shard">Optional shard for which mappings are being requested.</param>
 /// <param name="range">Optional range for which mappings are being requested.</param>
 /// <returns>Xml formatted request.</returns>
 internal static XElement GetAllShardMappingsLocal(
     IStoreShardMap shardMap,
     IStoreShard shard,
     ShardRange range)
 {
     return new XElement(
         @"GetAllShardMappingsLocal",
         StoreOperationRequestBuilder.s_lsmVersion,
         StoreObjectFormatterXml.WriteIStoreShardMap("ShardMap", shardMap),
         StoreObjectFormatterXml.WriteIStoreShard("Shard", shard),
         StoreObjectFormatterXml.WriteShardRange(range));
 }
 /// <summary>
 /// Converts a given shard range to xml.
 /// </summary>
 /// <param name="range">Input range.</param>
 /// <returns>XElement representing the given range.</returns>
 internal static XElement WriteShardRange(ShardRange range)
 {
     if (range == null)
     {
         return new XElement("Range", new XAttribute("Null", 1));
     }
     else
     {
         return new XElement("Range", new XAttribute("Null", 0),
             new XElement("MinValue", StringUtils.ByteArrayToString(range.Low.RawValue)),
             new XElement("MaxValue",
                 new XAttribute("Null", range.High.IsMax ? 1 : 0),
                 range.High.IsMax ? null : StringUtils.ByteArrayToString(range.High.RawValue)));
     }
 }
 /// <summary>
 /// Helper function to advance mapping iterators.
 /// </summary>
 /// <param name="iterator">The iterator to advance.</param>
 /// <param name="keyType">The data type of the map key.</param>
 /// <param name="nextMapping">Output value that will contain next mapping.</param>
 /// <param name="nextRange">Output value that will contain next range.</param>
 /// <param name="nextMinKey">Output value that will contain next min key.</param>
 private static void MoveToNextMapping(
     IEnumerator<IStoreMapping> iterator,
     ShardKeyType keyType,
     out IStoreMapping nextMapping,
     out ShardRange nextRange,
     out ShardKey nextMinKey)
 {
     nextMapping = iterator.MoveNext() ? iterator.Current : null;
     nextRange = nextMapping != null ? new ShardRange(
                         ShardKey.FromRawValue(keyType, nextMapping.MinValue),
                         ShardKey.FromRawValue(keyType, nextMapping.MaxValue)) : null;
     nextMinKey = nextRange != null ? nextRange.Low : null;
 }
 /// <summary>
 /// Sets the stub of StoreOperationFactory.CreateGetMappingsByRangeLocalOperation(ShardMapManager shardMapManager, ShardLocation location, String operationName, IStoreShardMap shardMap, IStoreShard shard, ShardRange range, Boolean ignoreFailure)
 /// </summary>
 public override IStoreOperationLocal CreateGetMappingsByRangeLocalOperation(ShardMapManager shardMapManager, ShardLocation location, string operationName, IStoreShardMap shardMap, IStoreShard shard, ShardRange range, bool ignoreFailure)
 {
     Func<ShardMapManager, ShardLocation, string, IStoreShardMap, IStoreShard, ShardRange, bool, IStoreOperationLocal> func1 = this.CreateGetMappingsByRangeLocalOperationShardMapManagerShardLocationStringIStoreShardMapIStoreShardShardRangeBoolean;
     if (func1 != null)
         return func1(shardMapManager, location, operationName, shardMap, shard, range, ignoreFailure);
     if (this.___callBase)
         return base.CreateGetMappingsByRangeLocalOperation(shardMapManager, location, operationName, shardMap, shard, range, ignoreFailure);
     return this.InstanceBehavior.Result<StubStoreOperationFactory, IStoreOperationLocal>(this, "CreateGetMappingsByRangeLocalOperation");
 }
 /// <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>
        /// Remove a mapping object from cache.
        /// </summary>
        /// <param name="sm">Storage maping object.</param>
        /// <remarks>
        /// Q: Do we ever need to remove multiple entries from the cache which cover the same range?
        /// A: Yes. Imagine that you have some stale mapping in the cache, user just simply performs 
        /// an AddRangeMapping operation on a subset of stale mapping range, now you should remove the 
        /// stale mapping.
        /// </remarks>
        internal override void Remove(IStoreMapping sm)
        {
            ShardKey minKey = ShardKey.FromRawValue(this.KeyType, sm.MinValue);
            ShardKey maxKey = ShardKey.FromRawValue(this.KeyType, sm.MaxValue);

            // Make range out of mapping key.
            ShardRange range = new ShardRange(minKey, maxKey);

            // Fast code path, where cache does contain the exact range.
            if (_mappingsByRange.ContainsKey(range))
            {
                _mappingsByRange.Remove(range);
            }
            else
            {
                int indexMin = this.GetIndexOfMappingWithClosestMinLessThanOrEqualToMinKey(minKey);
                int indexMax = this.GetIndexOfMappingWithClosestMaxGreaterThanOrEqualToMaxKey(maxKey);

                if (indexMin < 0)
                {
                    indexMin = 0;
                }

                if (indexMax >= _mappingsByRange.Keys.Count)
                {
                    indexMax = _mappingsByRange.Keys.Count - 1;
                }

                // Find first range with max greater than min key.
                for (; indexMin <= indexMax; indexMin++)
                {
                    ShardRange currentRange = _mappingsByRange.Keys[indexMin];
                    if (currentRange.High > minKey)
                    {
                        break;
                    }
                }

                // Find first range with min less than or equal to max key.
                for (; indexMax >= indexMin; indexMax--)
                {
                    ShardRange currentRange = _mappingsByRange.Keys[indexMax];
                    if (currentRange.Low <= maxKey)
                    {
                        break;
                    }
                }

                List<ShardRange> rangesToRemove = new List<ShardRange>();

                for (; indexMin <= indexMax; indexMin++)
                {
                    rangesToRemove.Add(_mappingsByRange.Keys[indexMin]);
                }

                foreach (ShardRange rangeToRemove in rangesToRemove)
                {
                    _mappingsByRange.Remove(rangeToRemove);
                }
            }
        }
Example #17
0
 /// <summary>
 /// Finds range mapping which contain the given range for the shard map. 
 /// If range is not given:
 ///     If shard is given, finds all mappings for the shard.
 ///     If shard is also not given, finds all the mappings.
 /// If range is given:
 ///     If shard is given, finds all mappings for the shard in the range.
 ///     If shard is not given, finds all the mappings in the range.
 /// </summary>
 /// <param name="ssm">Shard map to find mappings in.</param>
 /// <param name="range">Optional range to find mappings in.</param>
 /// <param name="shard">Shard to find mappings in.</param>
 /// <returns>Storage operation result.</returns>
 public virtual IStoreResults FindRangeMappingByRangeLocal(IStoreShardMap ssm, ShardRange range, IStoreShard shard)
 {
     try
     {
         return SqlStore.FindMappingByRangeLocalHelper(ssm, range, shard, @"__ShardManagement.smm_getAllRangeShardMappingsLocal");
     }
     catch (SqlException se)
     {
         throw new StoreException(
             Errors.SqlStore_ShardMap_AddRemoveUpdateFindMappingLocal_SqlException,
             se,
             "FindMappingsForRange",
             "Range",
             shard.Location);
     }
 }
Example #18
0
        /// <summary>
        /// Removes range mapping within existing range mapping.
        /// </summary>
        /// <param name="ssm">Shard map to remove range mapping to.</param>
        /// <param name="sm">Shard mapping to remove range from.</param>
        /// <param name="range">Range to remove.</param>
        /// <param name="lockOwnerId">Lock owner id of this mapping</param>
        /// <returns>Storage operation result.</returns>
        public virtual IStoreResults RemoveRangeWithinRangeMappingGlobal(IStoreShardMap ssm, IStoreMapping sm, ShardRange range, Guid lockOwnerId)
        {
            try
            {
                SqlResults result = new SqlResults();

                using (SqlCommand cmd = SqlTransactionScopeGlobal.CreateSqlCommand())
                {
                    cmd.CommandText = @"__ShardManagement.smm_removeRangeShardMappingWithinRangeGlobal";
                    cmd.CommandType = CommandType.StoredProcedure;

                    XElement input = new XElement(cmd.CommandText,
                        new XElement("gsm_version", SqlStoreGsmVersion.ToString()),
                        new XElement("sm_id", sm.ShardMapId.ToString()),
                        new XElement("lo_id", lockOwnerId.ToString()),
                        new XElement("sm_version", ssm.Version.ToString()),
                        new XElement("m_id", sm.Id.ToString()),
                        new XElement("m_min_value", StringUtils.ByteArrayToString(range.Low.RawValue)),
                        new XElement("m_max_value",
                            (range.High == null) ? null : StringUtils.ByteArrayToString(range.High.RawValue),
                            new XAttribute("is_null", (range.High == null) ? "true" : "false")
                            ),
                        new XElement("m_version", sm.Version.ToString())
                        );

                    SqlStore.AddCommandParameter(cmd, "@input", SqlDbType.Xml, ParameterDirection.Input, 0, input.ToString()); 
                    SqlParameter resultParam = SqlStore.AddCommandParameter(cmd, "@result", SqlDbType.Int, ParameterDirection.Output, 0, 0);

                    using (SqlDataReader reader = cmd.ExecuteReader())
                    {
                        result.Fetch(reader);
                    }

                    // Output parameter will be used to specify the outcome.
                    result.Result = (StoreResult)resultParam.Value;
                }

                return result;
            }
            catch (SqlException se)
            {
                throw new StoreException(
                    Errors.SqlStore_RangeShardMap_AddRemoveRange_SqlException,
                    se,
                    "RemoveRange",
                    ssm.Name);
            }
        }
Example #19
0
        public IEnumerable <RecoveryToken> DetectMappingDifferences(ShardLocation location, string shardMapName)
        {
            ExceptionUtils.DisallowNullArgument(location, "location");

            IList <RecoveryToken> listOfTokens = new List <RecoveryToken>();

            IStoreResults getShardsLocalResult;

            using (IStoreOperationLocal op = this.Manager.StoreOperationFactory.CreateGetShardsLocalOperation(
                       this.Manager,
                       location,
                       "DetectMappingDifferences"))
            {
                getShardsLocalResult = op.Do();
            }

            Debug.Assert(getShardsLocalResult.Result == StoreResult.Success);

            IEnumerable <IStoreShardMap> shardMaps =
                shardMapName == null ?
                getShardsLocalResult.StoreShardMaps :
                getShardsLocalResult.StoreShardMaps.Where(s => s.Name == shardMapName);

            IEnumerable <Tuple <IStoreShardMap, IStoreShard> > shardInfos =
                shardMaps
                .Select(sm => new Tuple <IStoreShardMap, IStoreShard>(
                            sm,
                            getShardsLocalResult.StoreShards.SingleOrDefault(s => s.ShardMapId == sm.Id)));

            foreach (Tuple <IStoreShardMap, IStoreShard> shardInfo in shardInfos)
            {
                IStoreShardMap ssmLocal = shardInfo.Item1;
                IStoreShard    ssLocal  = shardInfo.Item2;

                RecoveryToken token = new RecoveryToken();

                listOfTokens.Add(token);
                this.StoreShardMaps[token] = shardInfo;
                this.Locations[token]      = location;

                this.Inconsistencies[token] = new Dictionary <ShardRange, MappingDifference>();

                DefaultStoreShard dss = new DefaultStoreShard(
                    ssLocal.Id,
                    ssLocal.Version,
                    ssLocal.ShardMapId,
                    ssLocal.Location,
                    ssLocal.Status);

                // First get all local mappings.
                IStoreResults lsmMappings;

                using (IStoreOperationLocal op = this.Manager.StoreOperationFactory.CreateGetMappingsByRangeLocalOperation(
                           this.Manager,
                           location,
                           "DetectMappingDifferences",
                           ssmLocal,
                           dss,
                           null,
                           true))
                {
                    lsmMappings = op.Do();

                    if (lsmMappings.Result == StoreResult.ShardMapDoesNotExist)
                    {
                        // The shard needs to be re-attached. We are ignoring these errors in
                        // DetectMappingDifferences, since corruption is more profound than
                        // just inconsistent mappings.
                        // Alternatively, this shard belongs to a different shard map manager.
                        // Either way, we can't do anything about it here.
                        continue;
                    }
                }

                // Next build up a set of relevant global mappings.
                // This is the union of those mappings that are associated with this local shard
                // and those mappings which intersect with mappings found in the local shard.
                // We will partition these mappings based on ranges.
                IDictionary <ShardRange, IStoreMapping> relevantGsmMappings = new Dictionary <ShardRange, IStoreMapping>();

                IStoreResults gsmMappingsByMap;

                using (IStoreOperationGlobal op = this.Manager.StoreOperationFactory.CreateGetMappingsByRangeGlobalOperation(
                           this.Manager,
                           "DetectMappingDifferences",
                           ssmLocal,
                           dss,
                           null,
                           ShardManagementErrorCategory.Recovery,
                           false,
                           true /* ignore failures */))
                {
                    gsmMappingsByMap = op.Do();
                }

                if (gsmMappingsByMap.Result == StoreResult.ShardMapDoesNotExist)
                {
                    // The shard map is not properly attached to this GSM.
                    // This is beyond what we can handle resolving mappings.
                    continue;
                }

                foreach (IStoreMapping gsmMapping in gsmMappingsByMap.StoreMappings)
                {
                    ShardKey min = ShardKey.FromRawValue(ssmLocal.KeyType, gsmMapping.MinValue);

                    ShardKey max = null;

                    switch (ssmLocal.MapType)
                    {
                    case ShardMapType.Range:
                        max = ShardKey.FromRawValue(ssmLocal.KeyType, gsmMapping.MaxValue);
                        break;

                    default:
                        Debug.Assert(ssmLocal.MapType == ShardMapType.List);
                        max = ShardKey.FromRawValue(ssmLocal.KeyType, gsmMapping.MinValue).GetNextKey();
                        break;
                    }

                    ShardRange range = new ShardRange(min, max);

                    relevantGsmMappings[range] = gsmMapping;
                }

                // Next, for each of the mappings in lsmMappings, we need to augment
                // the gsmMappingsByMap by intersecting ranges.
                foreach (IStoreMapping lsmMapping in lsmMappings.StoreMappings)
                {
                    ShardKey min = ShardKey.FromRawValue(ssmLocal.KeyType, lsmMapping.MinValue);

                    IStoreResults gsmMappingsByRange;

                    if (ssmLocal.MapType == ShardMapType.Range)
                    {
                        ShardKey max = ShardKey.FromRawValue(ssmLocal.KeyType, lsmMapping.MaxValue);

                        ShardRange range = new ShardRange(min, max);

                        using (IStoreOperationGlobal op = this.Manager.StoreOperationFactory.CreateGetMappingsByRangeGlobalOperation(
                                   this.Manager,
                                   "DetectMappingDifferences",
                                   ssmLocal,
                                   null,
                                   range,
                                   ShardManagementErrorCategory.Recovery,
                                   false,
                                   true /* ignore failures */))
                        {
                            gsmMappingsByRange = op.Do();
                        }

                        if (gsmMappingsByRange.Result == StoreResult.ShardMapDoesNotExist)
                        {
                            // The shard was not properly attached.
                            // This is more than we can deal with in mapping resolution.
                            continue;
                        }
                    }
                    else
                    {
                        Debug.Assert(ssmLocal.MapType == ShardMapType.List);
                        using (IStoreOperationGlobal op = this.Manager.StoreOperationFactory.CreateFindMappingByKeyGlobalOperation(
                                   this.Manager,
                                   "DetectMappingDifferences",
                                   ssmLocal,
                                   min,
                                   CacheStoreMappingUpdatePolicy.OverwriteExisting,
                                   ShardManagementErrorCategory.Recovery,
                                   false,
                                   true /* ignore failures */))
                        {
                            gsmMappingsByRange = op.Do();

                            if (gsmMappingsByRange.Result == StoreResult.MappingNotFoundForKey ||
                                gsmMappingsByRange.Result == StoreResult.ShardMapDoesNotExist)
                            {
                                // * No intersections being found is fine. Skip to the next mapping.
                                // * The shard was not properly attached.
                                // This is more than we can deal with in mapping resolution.
                                continue;
                            }
                        }
                    }

                    foreach (IStoreMapping gsmMapping in gsmMappingsByRange.StoreMappings)
                    {
                        ShardKey retrievedMin = ShardKey.FromRawValue(ssmLocal.KeyType, gsmMapping.MinValue);

                        ShardRange retrievedRange = null;

                        switch (ssmLocal.MapType)
                        {
                        case ShardMapType.Range:
                            ShardKey retrievedMax = ShardKey.FromRawValue(ssmLocal.KeyType, gsmMapping.MaxValue);
                            retrievedRange = new ShardRange(retrievedMin, retrievedMax);
                            break;

                        default:
                            Debug.Assert(ssmLocal.MapType == ShardMapType.List);
                            retrievedMax   = ShardKey.FromRawValue(ssmLocal.KeyType, gsmMapping.MinValue).GetNextKey();
                            retrievedRange = new ShardRange(retrievedMin, retrievedMax);
                            break;
                        }

                        relevantGsmMappings[retrievedRange] = gsmMapping;
                    }
                }

                IList <MappingComparisonResult> comparisonResults = null;

                switch (ssmLocal.MapType)
                {
                case ShardMapType.Range:
                    comparisonResults = MappingComparisonUtils.CompareRangeMappings(
                        ssmLocal,
                        relevantGsmMappings.Values,
                        lsmMappings.StoreMappings);
                    break;

                default:
                    Debug.Assert(ssmLocal.MapType == ShardMapType.List);
                    comparisonResults = MappingComparisonUtils.ComparePointMappings(
                        ssmLocal,
                        relevantGsmMappings.Values,
                        lsmMappings.StoreMappings);
                    break;
                }

                // Now we have 2 sets of mappings. Each submapping generated from this function is
                //  1.) in the GSM only: report.
                //  2.) in the LSM only: report.
                //  3.) in both but with different version number: report.
                //  4.) in both with the same version number: skip.
                foreach (MappingComparisonResult r in comparisonResults)
                {
                    switch (r.MappingLocation)
                    {
                    case MappingLocation.MappingInShardMapOnly:
                    case MappingLocation.MappingInShardOnly:
                        break;

                    default:
                        Debug.Assert(r.MappingLocation == MappingLocation.MappingInShardMapAndShard);

                        if (r.ShardMapManagerMapping.Id == r.ShardMapping.Id)
                        {
                            // No conflict found, skip to the next range.
                            continue;
                        }
                        break;
                    }

                    // Store the inconsistency for later reporting.
                    this.Inconsistencies[token][r.Range] = new MappingDifference(
                        type: MappingDifferenceType.Range,
                        location: r.MappingLocation,
                        shardMap: r.ShardMap,
                        mappingForShard: r.ShardMapping,
                        mappingForShardMap: r.ShardMapManagerMapping);
                }
            }

            return(listOfTokens);
        }
Example #20
0
        private static IStoreResults FindMappingByRangeLocalHelper(IStoreShardMap ssm, ShardRange range, IStoreShard shard, string storedProcName)
        {
            SqlResults result = new SqlResults();

            using (SqlCommand cmd = SqlTransactionScopeLocal.CreateSqlCommand(shard.Location))
            {
                cmd.CommandText = storedProcName;
                cmd.CommandType = CommandType.StoredProcedure;

                XElement input = new XElement(storedProcName,
                    new XElement("lsm_version", SqlStoreLsmVersion.ToString()),
                    new XElement("sm_id", ssm.Id.ToString()),
                    new XElement("s_id", shard == null ? null : shard.Id.ToString(),
                        new XAttribute("is_null", (shard == null) ? "true" : "false")
                        ),
                    new XElement("m_min_value", range == null ? null : StringUtils.ByteArrayToString(range.Low.RawValue),
                        new XAttribute("is_null", (range == null) ? "true" : "false")
                        ),
                    new XElement("m_max_value", (range == null) ? null : StringUtils.ByteArrayToString(range.High.RawValue),
                        new XAttribute("is_null", (range == null) ? "true" : "false")
                        )
                    );

                SqlStore.AddCommandParameter(cmd, "@input", SqlDbType.Xml, ParameterDirection.Input, 0, input.ToString());
                SqlParameter resultParam = SqlStore.AddCommandParameter(cmd, "@result", SqlDbType.Int, ParameterDirection.Output, 0, 0);

                using (SqlDataReader reader = cmd.ExecuteReader())
                {
                    result.Fetch(reader);
                }

                // Output parameter will be used to specify the outcome.
                result.Result = (StoreResult)resultParam.Value;
            }

            return result;
        }
        public IEnumerable<RecoveryToken> DetectMappingDifferences(ShardLocation location, string shardMapName)
        {
            ExceptionUtils.DisallowNullArgument(location, "location");

            IList<RecoveryToken> listOfTokens = new List<RecoveryToken>();

            IStoreResults getShardsLocalResult;

            using (IStoreOperationLocal op = this.Manager.StoreOperationFactory.CreateGetShardsLocalOperation(
                this.Manager,
                location,
                "DetectMappingDifferences"))
            {
                getShardsLocalResult = op.Do();
            }

            Debug.Assert(getShardsLocalResult.Result == StoreResult.Success);

            IEnumerable<IStoreShardMap> shardMaps =
                shardMapName == null ?
                getShardsLocalResult.StoreShardMaps :
                getShardsLocalResult.StoreShardMaps.Where(s => s.Name == shardMapName);

            IEnumerable<Tuple<IStoreShardMap, IStoreShard>> shardInfos =
                shardMaps
                    .Select(sm => new Tuple<IStoreShardMap, IStoreShard>(
                        sm,
                        getShardsLocalResult.StoreShards.SingleOrDefault(s => s.ShardMapId == sm.Id)));

            foreach (Tuple<IStoreShardMap, IStoreShard> shardInfo in shardInfos)
            {
                IStoreShardMap ssmLocal = shardInfo.Item1;
                IStoreShard ssLocal = shardInfo.Item2;

                RecoveryToken token = new RecoveryToken();

                listOfTokens.Add(token);
                this.StoreShardMaps[token] = shardInfo;
                this.Locations[token] = location;

                this.Inconsistencies[token] = new Dictionary<ShardRange, MappingDifference>();

                DefaultStoreShard dss = new DefaultStoreShard(
                    ssLocal.Id,
                    ssLocal.Version,
                    ssLocal.ShardMapId,
                    ssLocal.Location,
                    ssLocal.Status);

                // First get all local mappings.
                IStoreResults lsmMappings;

                using (IStoreOperationLocal op = this.Manager.StoreOperationFactory.CreateGetMappingsByRangeLocalOperation(
                    this.Manager,
                    location,
                    "DetectMappingDifferences",
                    ssmLocal,
                    dss,
                    null,
                    true))
                {
                    lsmMappings = op.Do();

                    if (lsmMappings.Result == StoreResult.ShardMapDoesNotExist)
                    {
                        // The shard needs to be re-attached. We are ignoring these errors in 
                        // DetectMappingDifferences, since corruption is more profound than 
                        // just inconsistent mappings.
                        // Alternatively, this shard belongs to a different shard map manager.
                        // Either way, we can't do anything about it here.
                        continue;
                    }
                }

                // Next build up a set of relevant global mappings.
                // This is the union of those mappings that are associated with this local shard
                // and those mappings which intersect with mappings found in the local shard.
                // We will partition these mappings based on ranges.
                IDictionary<ShardRange, IStoreMapping> relevantGsmMappings = new Dictionary<ShardRange, IStoreMapping>();

                IStoreResults gsmMappingsByMap;

                using (IStoreOperationGlobal op = this.Manager.StoreOperationFactory.CreateGetMappingsByRangeGlobalOperation(
                    this.Manager,
                    "DetectMappingDifferences",
                    ssmLocal,
                    dss,
                    null,
                    ShardManagementErrorCategory.Recovery,
                    false,
                    true/* ignore failures */))
                {
                    gsmMappingsByMap = op.Do();
                }

                if (gsmMappingsByMap.Result == StoreResult.ShardMapDoesNotExist)
                {
                    // The shard map is not properly attached to this GSM.
                    // This is beyond what we can handle resolving mappings.
                    continue;
                }

                foreach (IStoreMapping gsmMapping in gsmMappingsByMap.StoreMappings)
                {
                    ShardKey min = ShardKey.FromRawValue(ssmLocal.KeyType, gsmMapping.MinValue);

                    ShardKey max = null;

                    switch (ssmLocal.MapType)
                    {
                        case ShardMapType.Range:
                            max = ShardKey.FromRawValue(ssmLocal.KeyType, gsmMapping.MaxValue);
                            break;

                        default:
                            Debug.Assert(ssmLocal.MapType == ShardMapType.List);
                            max = ShardKey.FromRawValue(ssmLocal.KeyType, gsmMapping.MinValue).GetNextKey();
                            break;
                    }

                    ShardRange range = new ShardRange(min, max);

                    relevantGsmMappings[range] = gsmMapping;
                }

                // Next, for each of the mappings in lsmMappings, we need to augment 
                // the gsmMappingsByMap by intersecting ranges.
                foreach (IStoreMapping lsmMapping in lsmMappings.StoreMappings)
                {
                    ShardKey min = ShardKey.FromRawValue(ssmLocal.KeyType, lsmMapping.MinValue);

                    IStoreResults gsmMappingsByRange;

                    if (ssmLocal.MapType == ShardMapType.Range)
                    {
                        ShardKey max = ShardKey.FromRawValue(ssmLocal.KeyType, lsmMapping.MaxValue);

                        ShardRange range = new ShardRange(min, max);

                        using (IStoreOperationGlobal op = this.Manager.StoreOperationFactory.CreateGetMappingsByRangeGlobalOperation(
                            this.Manager,
                            "DetectMappingDifferences",
                            ssmLocal,
                            null,
                            range,
                            ShardManagementErrorCategory.Recovery,
                            false,
                            true/* ignore failures */))
                        {
                            gsmMappingsByRange = op.Do();
                        }

                        if (gsmMappingsByRange.Result == StoreResult.ShardMapDoesNotExist)
                        {
                            // The shard was not properly attached. 
                            // This is more than we can deal with in mapping resolution.
                            continue;
                        }
                    }
                    else
                    {
                        Debug.Assert(ssmLocal.MapType == ShardMapType.List);
                        using (IStoreOperationGlobal op = this.Manager.StoreOperationFactory.CreateFindMappingByKeyGlobalOperation(
                            this.Manager,
                            "DetectMappingDifferences",
                            ssmLocal,
                            min,
                            CacheStoreMappingUpdatePolicy.OverwriteExisting,
                            ShardManagementErrorCategory.Recovery,
                            false,
                            true/* ignore failures */))
                        {
                            gsmMappingsByRange = op.Do();

                            if (gsmMappingsByRange.Result == StoreResult.MappingNotFoundForKey ||
                                gsmMappingsByRange.Result == StoreResult.ShardMapDoesNotExist)
                            {
                                // * No intersections being found is fine. Skip to the next mapping.
                                // * The shard was not properly attached. 
                                // This is more than we can deal with in mapping resolution.
                                continue;
                            }
                        }
                    }

                    foreach (IStoreMapping gsmMapping in gsmMappingsByRange.StoreMappings)
                    {
                        ShardKey retrievedMin = ShardKey.FromRawValue(ssmLocal.KeyType, gsmMapping.MinValue);

                        ShardRange retrievedRange = null;

                        switch (ssmLocal.MapType)
                        {
                            case ShardMapType.Range:
                                ShardKey retrievedMax = ShardKey.FromRawValue(ssmLocal.KeyType, gsmMapping.MaxValue);
                                retrievedRange = new ShardRange(retrievedMin, retrievedMax);
                                break;

                            default:
                                Debug.Assert(ssmLocal.MapType == ShardMapType.List);
                                retrievedMax = ShardKey.FromRawValue(ssmLocal.KeyType, gsmMapping.MinValue).GetNextKey();
                                retrievedRange = new ShardRange(retrievedMin, retrievedMax);
                                break;
                        }

                        relevantGsmMappings[retrievedRange] = gsmMapping;
                    }
                }

                IList<MappingComparisonResult> comparisonResults = null;

                switch (ssmLocal.MapType)
                {
                    case ShardMapType.Range:
                        comparisonResults = MappingComparisonUtils.CompareRangeMappings(
                            ssmLocal,
                            relevantGsmMappings.Values,
                            lsmMappings.StoreMappings);
                        break;

                    default:
                        Debug.Assert(ssmLocal.MapType == ShardMapType.List);
                        comparisonResults = MappingComparisonUtils.ComparePointMappings(
                            ssmLocal,
                            relevantGsmMappings.Values,
                            lsmMappings.StoreMappings);
                        break;
                }

                // Now we have 2 sets of mappings. Each submapping generated from this function is
                //  1.) in the GSM only: report.
                //  2.) in the LSM only: report.
                //  3.) in both but with different version number: report.
                //  4.) in both with the same version number: skip.
                foreach (MappingComparisonResult r in comparisonResults)
                {
                    switch (r.MappingLocation)
                    {
                        case MappingLocation.MappingInShardMapOnly:
                        case MappingLocation.MappingInShardOnly:
                            break;
                        default:
                            Debug.Assert(r.MappingLocation == MappingLocation.MappingInShardMapAndShard);

                            if (r.ShardMapManagerMapping.Id == r.ShardMapping.Id)
                            {
                                // No conflict found, skip to the next range.
                                continue;
                            }
                            break;
                    }

                    // Store the inconsistency for later reporting.
                    this.Inconsistencies[token][r.Range] = new MappingDifference(
                        type: MappingDifferenceType.Range,
                        location: r.MappingLocation,
                        shardMap: r.ShardMap,
                        mappingForShard: r.ShardMapping,
                        mappingForShardMap: r.ShardMapManagerMapping);
                }
            }

            return listOfTokens;
        }
Example #22
0
 /// <summary>
 /// Finds point mapping which contain the given range for the shard map. 
 /// If range is not given:
 ///     If shard is given, finds all mappings for the shard.
 ///     If shard is also not given, finds all the mappings.
 /// If range is given:
 ///     If shard is given, finds all mappings for the shard in the range.
 ///     If shard is not given, finds all the mappings in the range.
 /// </summary>
 /// <param name="ssm">Shard map to find mappings in.</param>
 /// <param name="range">Optional range to find mappings in.</param>
 /// <param name="shard">Option shard to find mappings in.</param>
 /// <returns>Storage operation result.</returns>
 public virtual IStoreResults FindPointMappingByRangeGlobal(IStoreShardMap ssm, ShardRange range, IStoreShard shard)
 {
     try
     {
         return SqlStore.FindMappingByRangeGlobalHelper(ssm, range, shard, @"__ShardManagement.smm_getAllPointShardMappingsGlobal");
     }
     catch (SqlException se)
     {
         throw new StoreException(
             Errors.SqlStore_ShardMap_AddRemoveUpdateFindMappingGlobal_SqlException,
             se,
             "FindMappingsForRange",
             "Point",
             ssm.Name);
     }
 }