/// <summary> /// Handles the shardlet move request from tje request queue. /// </summary> /// <param name="request">The request.</param> /// <param name="queue">The queue.</param> /// <param name="uniqueProcessID">A unique process identifier that can be set to maintain state between moves.</param> public static void HandleShardletMoveRequest(ShardletMoveRequest request, IShardSetActionQueue queue, Guid uniqueProcessID) { Action <ShardletMoveRequest> process = x => { var shardlet = Load(x.ShardSetName, x.ShardingKey); var destinationShard = new RangeShard { Catalog = x.DestinationCatalog, ServerInstanceName = x.DestinationServerInstanceName }; shardlet.MoveToShard(destinationShard, x.Pin, x.DeleteOnMove, uniqueProcessID); }; Action <ShardletMoveRequest> complete = x => { var message = GetCompletionMessage("ShardletMoveRequest", x); queue.SendQueueProcessingEvent(message); }; Action <ShardletMoveRequest> error = x => { var message = GetErrorMessage("ShardletMoveRequest", x); queue.SendQueueProcessingEvent(message); }; 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()); }
/// <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; } }