Beispiel #1
0
        /// <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)
        {
            // Make key out of mapping key.
            ShardKey key = ShardKey.FromRawValue(this.KeyType, sm.MinValue);

            CacheMapping cm;

            // 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 &&
                _mappingsByKey.TryGetValue(key, out cm) &&
                cm.Mapping.Id == sm.Id /*&&
                                        * TimerUtils.ElapsedMillisecondsSince(cm.CreationTime) >= cm.TimeToLiveMilliseconds */)
            {
                cm = new CacheMapping(sm, CacheMapper.CalculateNewTimeToLiveMilliseconds(cm));
            }
            else
            {
                cm = new CacheMapping(sm);
            }

            // Remove existing entry.
            this.Remove(sm);

            // Add the entry to lookup table by Key.
            _mappingsByKey.Add(key, cm);
        }
Beispiel #2
0
        /// <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);
        }
Beispiel #3
0
        /// <summary>
        /// Remove a mapping object from cache.
        /// </summary>
        /// <param name="sm">Storage maping object.</param>
        internal override void Remove(IStoreMapping sm)
        {
            // Make key value out of mapping key.
            ShardKey key = ShardKey.FromRawValue(this.KeyType, sm.MinValue);

            // Remove existing entry.
            if (_mappingsByKey.ContainsKey(key))
            {
                _mappingsByKey.Remove(key);
            }
        }
        /// <summary>
        /// Internal constructor used for deserialization from store representation of
        /// the mapping object.
        /// </summary>
        /// <param name="manager">Owning ShardMapManager.</param>
        /// <param name="shardMap">Owning shard map.</param>
        /// <param name="mapping">Storage representation of the mapping.</param>
        internal PointMapping(
            ShardMapManager manager,
            ShardMap shardMap,
            IStoreMapping mapping)
        {
            Debug.Assert(manager != null);
            this.Manager = manager;

            Debug.Assert(mapping != null);
            Debug.Assert(mapping.ShardMapId != default(Guid));
            Debug.Assert(mapping.StoreShard.ShardMapId != default(Guid));
            this.StoreMapping = mapping;

            _shard = new Shard(this.Manager, shardMap, mapping.StoreShard);

            this.Key   = ShardKey.FromRawValue(ShardKey.ShardKeyTypeFromType(typeof(TKey)), mapping.MinValue);
            this.Value = (TKey)this.Key.Value;
        }
        /// <summary>
        /// Internal constructor used for deserialization from store representation of
        /// the mapping object.
        /// </summary>
        /// <param name="manager">Owning ShardMapManager.</param>
        /// <param name="shardMap">Owning shard map.</param>
        /// <param name="mapping">Storage representation of the mapping.</param>
        internal RangeMapping(
            ShardMapManager manager,
            ShardMap shardMap,
            IStoreMapping mapping)
        {
            Debug.Assert(manager != null);
            this.Manager = manager;

            Debug.Assert(mapping != null);
            Debug.Assert(mapping.ShardMapId != default(Guid));
            Debug.Assert(mapping.StoreShard.ShardMapId != default(Guid));
            this.StoreMapping = mapping;

            _shard = new Shard(this.Manager, shardMap, mapping.StoreShard);

            this.Range = new ShardRange(
                ShardKey.FromRawValue(ShardKey.ShardKeyTypeFromType(typeof(TKey)), mapping.MinValue),
                ShardKey.FromRawValue(ShardKey.ShardKeyTypeFromType(typeof(TKey)), mapping.MaxValue));

            this.Value = this.Range.High.IsMax ?
                         new Range <TKey>(this.Range.Low.GetValue <TKey>()) :
                         new Range <TKey>(this.Range.Low.GetValue <TKey>(), this.Range.High.GetValue <TKey>());
        }
Beispiel #6
0
        /// <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);
        }
Beispiel #7
0
        /// <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);
                }
            }
        }
        /// <summary>
        /// Finds all mappings to be purged based on the given input ranges.
        /// </summary>
        /// <param name="ts">GSM transaction scope.</param>
        /// <returns>Mappings which are to be removed.</returns>
        private IEnumerable <IStoreMapping> GetMappingsToPurge(IStoreTransactionScope ts)
        {
            // Find all the mappings in GSM belonging to the shard
            IStoreResults gsmMappingsByShard = ts.ExecuteOperation(
                StoreOperationRequestBuilder.SpGetAllShardMappingsGlobal,
                StoreOperationRequestBuilder.GetAllShardMappingsGlobal(_shardMap, _shard, null));

            if (gsmMappingsByShard.Result != StoreResult.Success)
            {
                // Possible errors are:
                // StoreResult.ShardMapDoesNotExist
                // StoreResult.StoreVersionMismatch
                // StoreResult.MissingParametersForStoredProcedure
                throw StoreOperationErrorHandler.OnRecoveryErrorGlobal(
                          gsmMappingsByShard,
                          _shardMap,
                          _shard,
                          ShardManagementErrorCategory.Recovery,
                          this.OperationName,
                          StoreOperationRequestBuilder.SpGetAllShardMappingsGlobal);
            }

            IDictionary <ShardRange, IStoreMapping> intersectingMappings = new Dictionary <ShardRange, IStoreMapping>();

            foreach (IStoreMapping gsmMappingByShard in gsmMappingsByShard.StoreMappings)
            {
                ShardKey min = ShardKey.FromRawValue(
                    _shardMap.KeyType,
                    gsmMappingByShard.MinValue);

                ShardKey max = null;

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

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

                intersectingMappings.Add(new ShardRange(min, max), gsmMappingByShard);
            }

            // We need to discover, also, the range of intersecting mappings, so we can transitively detect
            // inconsistencies with other shards.
            foreach (IStoreMapping lsmMapping in _mappingsToRemove)
            {
                ShardKey min = ShardKey.FromRawValue(_shardMap.KeyType, lsmMapping.MinValue);

                IStoreResults gsmMappingsByRange;

                switch (_shardMap.MapType)
                {
                case ShardMapType.Range:
                    gsmMappingsByRange = ts.ExecuteOperation(
                        StoreOperationRequestBuilder.SpGetAllShardMappingsGlobal,
                        StoreOperationRequestBuilder.GetAllShardMappingsGlobal(
                            _shardMap,
                            null,
                            new ShardRange(
                                min,
                                ShardKey.FromRawValue(_shardMap.KeyType, lsmMapping.MaxValue))));
                    break;

                default:
                    Debug.Assert(_shardMap.MapType == ShardMapType.List);
                    gsmMappingsByRange = ts.ExecuteOperation(
                        StoreOperationRequestBuilder.SpFindShardMappingByKeyGlobal,
                        StoreOperationRequestBuilder.FindShardMappingByKeyGlobal(
                            _shardMap,
                            min));
                    break;
                }

                if (gsmMappingsByRange.Result != StoreResult.Success)
                {
                    if (gsmMappingsByRange.Result != StoreResult.MappingNotFoundForKey)
                    {
                        // Possible errors are:
                        // StoreResult.ShardMapDoesNotExist
                        // StoreResult.StoreVersionMismatch
                        // StoreResult.MissingParametersForStoredProcedure
                        throw StoreOperationErrorHandler.OnRecoveryErrorGlobal(
                                  gsmMappingsByRange,
                                  _shardMap,
                                  _shard,
                                  ShardManagementErrorCategory.Recovery,
                                  this.OperationName,
                                  _shardMap.MapType == ShardMapType.Range ?
                                  StoreOperationRequestBuilder.SpGetAllShardMappingsGlobal :
                                  StoreOperationRequestBuilder.SpFindShardMappingByKeyGlobal);
                    }
                    else
                    {
                        // No intersections being found is fine. Skip to the next mapping.
                        Debug.Assert(_shardMap.MapType == ShardMapType.List);
                    }
                }
                else
                {
                    foreach (IStoreMapping gsmMappingByRange in gsmMappingsByRange.StoreMappings)
                    {
                        ShardKey minGlobal = ShardKey.FromRawValue(_shardMap.KeyType, gsmMappingByRange.MinValue);
                        ShardKey maxGlobal = null;

                        switch (_shardMap.MapType)
                        {
                        case ShardMapType.Range:
                            maxGlobal = ShardKey.FromRawValue(_shardMap.KeyType, gsmMappingByRange.MaxValue);
                            break;

                        default:
                            Debug.Assert(_shardMap.MapType == ShardMapType.List);
                            maxGlobal = ShardKey.FromRawValue(_shardMap.KeyType, gsmMappingByRange.MinValue).GetNextKey();
                            break;
                        }

                        intersectingMappings[new ShardRange(minGlobal, maxGlobal)] = gsmMappingByRange;
                    }
                }
            }

            return(intersectingMappings.Values);
        }