Exemplo n.º 1
0
        /// <summary>
        /// Selects one of the shard maps (either local or global) as a source of truth and brings
        /// mappings on both shard maps in sync.
        /// </summary>
        /// <param name="token">Recovery token returned from <see cref="DetectMappingDifferences(ShardLocation, string)"/>.</param>
        /// <param name="resolution">The resolution strategy to be used for resolution.</param>
        /// <remarks>
        /// Note that this method can cause unrecoverable data loss. Make sure you have taken backups or copies
        /// of your databases and only then proceed with great care.
        /// </remarks>
        public void ResolveMappingDifferences(
            RecoveryToken token,
            MappingDifferenceResolution resolution)
        {
            switch (resolution)
            {
            case MappingDifferenceResolution.KeepShardMapMapping:
                this.RestoreShardFromShardmap(token);
                break;

            case MappingDifferenceResolution.KeepShardMapping:
                this.RestoreShardMapFromShard(token);
                break;

            case MappingDifferenceResolution.Ignore:
                break;

            default:
                Debug.Fail("Unexpected value for MappingDifferenceResolution.");
                return;
            }

            this.StoreShardMaps.Remove(token);
            this.Locations.Remove(token);
            this.Inconsistencies.Remove(token);
        }
Exemplo n.º 2
0
        /// <summary>
        /// Given a collection of shard locations, reconstructs the shard map manager based on information
        /// stored in the individual shards.
        /// If the information in the individual shard maps is or becomes inconsistent, behavior is undefined.
        /// No cross shard locks are taken, so if any shards become inconsistent during the execution of this
        /// method, the final state of the global shard map may be corrupt.
        /// </summary>
        /// <param name="operationName">Operation name.</param>
        /// <param name="shardLocations">Collection of shard locations.</param>
        /// <param name="resolutionStrategy">Strategy for resolving the mapping differences.</param>
        /// <param name="shardMapName">Optional name of shard map. If omitted, will attempt to recover from all shard maps present on each shard.</param>
        private void RebuildMappingsHelper(
            string operationName,
            IEnumerable <ShardLocation> shardLocations,
            MappingDifferenceResolution resolutionStrategy,
            string shardMapName = null)
        {
            Debug.Assert(shardLocations != null);

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

            // Collect the shard map-shard pairings to recover. Give each of these pairings a token.
            foreach (ShardLocation shardLocation in shardLocations)
            {
                IStoreResults getShardsLocalResult;

                using (IStoreOperationLocal op = this.Manager.StoreOperationFactory.CreateGetShardsLocalOperation(
                           this.Manager,
                           shardLocation,
                           operationName))
                {
                    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)
                {
                    RecoveryToken token = new RecoveryToken();

                    idsToProcess.Add(token);

                    this.StoreShardMaps[token] = shardInfo;
                    this.Locations[token]      = shardLocation;
                }
            }

            // Recover from the shard map-shard pairing corresponding to the collected token.
            foreach (RecoveryToken token in idsToProcess)
            {
                this.ResolveMappingDifferences(token, resolutionStrategy);

                this.StoreShardMaps.Remove(token);
                this.Locations.Remove(token);
            }
        }
Exemplo n.º 3
0
        /// <summary>
        /// Given a collection of shard locations, reconstructs the shard map manager based on information
        /// stored in the individual shards.
        /// If the information in the individual shard maps is or becomes inconsistent, behavior is undefined.
        /// No cross shard locks are taken, so if any shards become inconsistent during the execution of this
        /// method, the final state of the global shard map may be corrupt.
        /// </summary>
        /// <param name="operationName">Operation name.</param>
        /// <param name="shardLocations">Collection of shard locations.</param>
        /// <param name="resolutionStrategy">Strategy for resolving the mapping differences.</param>
        /// <param name="shardMapName">Optional name of shard map. If omitted, will attempt to recover from all shard maps present on each shard.</param>
        private void RebuildMappingsHelper(
            string operationName,
            IEnumerable<ShardLocation> shardLocations,
            MappingDifferenceResolution resolutionStrategy,
            string shardMapName = null)
        {
            Debug.Assert(shardLocations != null);

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

            // Collect the shard map-shard pairings to recover. Give each of these pairings a token.
            foreach (ShardLocation shardLocation in shardLocations)
            {
                IStoreResults getShardsLocalResult;

                using (IStoreOperationLocal op = this.Manager.StoreOperationFactory.CreateGetShardsLocalOperation(
                    this.Manager,
                    shardLocation,
                    operationName))
                {
                    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)
                {
                    RecoveryToken token = new RecoveryToken();

                    idsToProcess.Add(token);

                    this.StoreShardMaps[token] = shardInfo;
                    this.Locations[token] = shardLocation;
                }
            }

            // Recover from the shard map-shard pairing corresponding to the collected token.
            foreach (RecoveryToken token in idsToProcess)
            {
                this.ResolveMappingDifferences(token, resolutionStrategy);

                this.StoreShardMaps.Remove(token);
                this.Locations.Remove(token);
            }
        }
Exemplo n.º 4
0
        /// <summary>
        /// Selects one of the shard maps (either local or global) as a source of truth and brings 
        /// mappings on both shard maps in sync.
        /// </summary>
        /// <param name="token">Recovery token returned from <see cref="DetectMappingDifferences(ShardLocation, string)"/>.</param>
        /// <param name="resolution">The resolution strategy to be used for resolution.</param>
        /// <remarks>
        /// Note that this method can cause unrecoverable data loss. Make sure you have taken backups or copies 
        /// of your databases and only then proceed with great care.
        /// </remarks>
        public void ResolveMappingDifferences(
            RecoveryToken token,
            MappingDifferenceResolution resolution)
        {
            switch (resolution)
            {
                case MappingDifferenceResolution.KeepShardMapMapping:
                    this.RestoreShardFromShardmap(token);
                    break;
                case MappingDifferenceResolution.KeepShardMapping:
                    this.RestoreShardMapFromShard(token);
                    break;
                case MappingDifferenceResolution.Ignore:
                    break;
                default:
                    Debug.Fail("Unexpected value for MappingDifferenceResolution.");
                    return;
            }

            this.StoreShardMaps.Remove(token);
            this.Locations.Remove(token);
            this.Inconsistencies.Remove(token);
        }