/// <summary>
        /// Copies the shardlet using the shard set driver for the shard.
        /// </summary>
        /// <param name="sourceShard">The current shard.</param>
        /// <param name="destinationShard">The shard.</param>
        /// <param name="shardingKey">The sharding key.</param>
        /// <param name="uniqueProcessID">The unique process identifier.</param>
        public virtual void CopyShardlet(ShardBase sourceShard, ShardBase destinationShard, string shardingKey,
                                         Guid uniqueProcessID)
        {
            var driver = GetShardSetDriver();

            driver.CopyShardlet(sourceShard, destinationShard, this, shardingKey, uniqueProcessID);
        }
        /// <summary>
        /// Deletes the shardlet using the shard set driver for the shard.
        /// </summary>
        /// <param name="shard">The shard.</param>
        /// <param name="shardingKey">The sharding key.</param>
        public virtual void DeleteShardlet(ShardBase shard, string shardingKey)
        {
            var driver = GetShardSetDriver();

            driver.DeleteShardlet(shard, this, shardingKey);
        }
        /// <summary>
        /// Moves to shard.
        /// </summary>
        /// <param name="shard">The shard to move the ShardLet data to.</param>
        /// <param name="pin">if set to <c>true</c> add the shard to the pinned shard list.</param>
        /// <param name="deleteOnMove">if set to <c>true</c> delete the Shardlet data from the existing Shard after move.</param>
        /// <param name="uniqueProcessID">A unique process identifier that can be set to maintain state between moves.</param>
        /// <param name="queueRequest">if set to <c>true</c> queue the shard move rather than executing it immediately.</param>
        public void MoveToShard(ShardBase shard, bool pin, bool deleteOnMove, Guid uniqueProcessID,
                                bool queueRequest = false)
        {
            if (queueRequest)
            {
                var request =
                    new ShardletMoveRequest
                {
                    DestinationCatalog            = shard.Catalog,
                    DestinationServerInstanceName = shard.ServerInstanceName,
                    SourceCatalog            = Catalog,
                    SourceServerInstanceName = ServerInstanceName,
                    DistributionKey          = DistributionKey,
                    ShardingKey     = ShardingKey,
                    ShardSetName    = ShardSetName,
                    DeleteOnMove    = deleteOnMove,
                    UniqueProcessID = uniqueProcessID,
                    Pin             = pin
                };

                request.Save();

                return;
            }

            var shardSetConnectionDriver = ScaleOutShardletManager.GetManager().GetShardletConnectionDriver(ShardSetName);

            try
            {
                // change the state to read only in the map and update th epin status
                Status = ShardletStatus.Moving;
                Pinned = pin;
                shardSetConnectionDriver.PublishShardlet(this);

                // terminate all existing connections
                shardSetConnectionDriver.TerminateConnections(this);

                // copy the shardlet data
                var shardSetConfig = ShardSetConfig.LoadCurrent(ShardSetName);

                var currentShard =
                    new RangeShard
                {
                    Catalog            = Catalog,
                    ServerInstanceName = ServerInstanceName,
                };

                shardSetConfig.CopyShardlet(currentShard, shard, ShardingKey, uniqueProcessID);

                // update the status and set the new catalog and instance in the shard map
                Catalog            = shard.Catalog;
                ServerInstanceName = shard.ServerInstanceName;
                Status             = ShardletStatus.Active;

                shardSetConnectionDriver.PublishShardlet(this);

                if (deleteOnMove)
                {
                    shardSetConfig.DeleteShardlet(currentShard, ShardingKey);
                }
            }
            catch (Exception)
            {
                Status = ShardletStatus.Active;
                shardSetConnectionDriver.PublishShardlet(this);

                throw;
            }
        }