/// <summary>
        /// Publishes the shard map for the shard set.
        /// </summary>
        /// <param name="queueRequest">if set to <c>true</c> queue request.</param>
        public virtual void PublishShardMap(bool queueRequest = false)
        {
            var previousShardMap = -1;

            //This could be null because it might be the first time the shard map is published.
            if (CurrentPublishedShardMapID.HasValue)
            {
                previousShardMap = CurrentPublishedShardMapID.Value;
            }

            var request =
                new ShardMapPublishingRequest
            {
                NewShardMapID     = ShardMap.ShardMapID,
                ShardSetName      = ShardSetName,
                CurrentShardMapID = previousShardMap
            };

            if (queueRequest)
            {
                request.Save();
                return;
            }

            ProcessShardMapPublishingRequest(request, this);
        }
 private static void CompleteShardMapPublishingRequest(ShardSetConfig config,
                                                       ShardMapPublishingRequest shardMapPublishingRequest)
 {
     //todo: this is saving a whole'nother config rathr thanjust incrementing the "current" config map in force
     config.CurrentPublishedShardMapID = shardMapPublishingRequest.NewShardMapID;
     config.Save();
 }
        /// <summary>
        /// Handles the shard map publishing request and processes it against the shard set driver.
        /// </summary>
        /// <param name="request">The shard map publishing request.</param>
        /// <param name="queue">The queue.</param>
        public static void HandleShardMapPublishingRequest(ShardMapPublishingRequest request,
                                                           IShardSetActionQueue queue)
        {
            var shardSetConfig = GetCurrentShardSetConfig(request.ShardSetName);

            Action <ShardMapPublishingRequest> process =
                x =>
            {
                ProcessShardMapPublishingRequest(x, shardSetConfig);

                if (!request.ShouldUpdateShardMap)
                {
                    return;
                }

                PublishRangeMap(shardSetConfig.ShardSetName, request.CurrentShardMapID, request.NewShardMapID);
            };

            Action <ShardMapPublishingRequest> complete =
                x =>
            {
                CompleteShardMapPublishingRequest(shardSetConfig, x);
                queue.SendQueueProcessingEvent(GetCompletionMessage("ShardMapPublishingRequest", x));
            };

            Action <ShardMapPublishingRequest> error =
                x => queue.SendQueueProcessingEvent(GetErrorMessage("ShardMapPublishingRequest", x));

            request.Process(process, complete, error);
        }
        private static void ProcessShardMapPublishingRequest(ShardMapPublishingRequest shardMapPublishingRequest,
                                                             ShardSetConfig shardSetConfig)
        {
            var shardSetName             = shardMapPublishingRequest.ShardSetName;
            var shardSetConnectionDriver = GetShardSetConnectionDriver(shardSetName);

            // to do - may need to page
            var shardlets = shardSetConnectionDriver.GetShardlets(shardSetName);

            foreach (var shardlet in shardlets)
            {
                // skip if shardlet is pinned
                if (shardlet.Pinned)
                {
                    continue;
                }

                // get the matching range shard for this shardlet based on the range map
                var rangeShard =
                    shardSetConfig.ShardMap.Shards
                    .FirstOrDefault(rs => rs.HighDistributionKey > shardlet.DistributionKey);

                // skip if we cannot find a range.
                if (rangeShard == null)
                {
                    continue;
                }

                // determine if the shardlet needs to be moved
                if (rangeShard.ServerInstanceName == shardlet.ServerInstanceName &&
                    rangeShard.Catalog == shardlet.Catalog)
                {
                    continue;
                }

                var request =
                    new ShardletMoveRequest
                {
                    DestinationCatalog            = rangeShard.Catalog,
                    DestinationServerInstanceName = shardlet.ServerInstanceName,
                    SourceCatalog            = shardlet.Catalog,
                    SourceServerInstanceName = shardlet.ServerInstanceName,
                    DistributionKey          = shardlet.DistributionKey,
                    ShardingKey  = shardlet.ShardingKey,
                    ShardSetName = shardlet.ShardSetName,
                    DeleteOnMove = true,
                    Pin          = false
                };

                request.Save();
            }

            // todo: do this save in parallel
            //var parallelOptions = GetParallelOptions();

            //Parallel.ForEach(shardletMoveRequests, parallelOptions,
            //    shardletMoveRequest => shardletMoveRequest.Save());
        }