本文整理汇总了Golang中github.com/youtube/vitess/go/vt/topo/topoproto.KeyspaceShardString函数的典型用法代码示例。如果您正苦于以下问题:Golang KeyspaceShardString函数的具体用法?Golang KeyspaceShardString怎么用?Golang KeyspaceShardString使用的例子?那么恭喜您, 这里精选的函数代码示例或许可以为您提供帮助。
在下文中一共展示了KeyspaceShardString函数的15个代码示例,这些例子默认根据受欢迎程度排序。您可以为喜欢或者感觉有用的代码点赞,您的评价将有助于系统推荐出更棒的Golang代码示例。
示例1: findDestinationMasters
// findDestinationMasters finds for each destination shard the current master.
func (scw *SplitCloneWorker) findDestinationMasters(ctx context.Context) error {
scw.setState(WorkerStateFindTargets)
// Make sure we find a master for each destination shard and log it.
scw.wr.Logger().Infof("Finding a MASTER tablet for each destination shard...")
for _, si := range scw.destinationShards {
waitCtx, waitCancel := context.WithTimeout(ctx, *waitForHealthyTabletsTimeout)
defer waitCancel()
if err := scw.tsc.WaitForTablets(waitCtx, scw.cell, si.Keyspace(), si.ShardName(), []topodatapb.TabletType{topodatapb.TabletType_MASTER}); err != nil {
return fmt.Errorf("cannot find MASTER tablet for destination shard for %v/%v (in cell: %v): %v", si.Keyspace(), si.ShardName(), scw.cell, err)
}
masters := scw.tsc.GetHealthyTabletStats(si.Keyspace(), si.ShardName(), topodatapb.TabletType_MASTER)
if len(masters) == 0 {
return fmt.Errorf("cannot find MASTER tablet for destination shard for %v/%v (in cell: %v) in HealthCheck: empty TabletStats list", si.Keyspace(), si.ShardName(), scw.cell)
}
master := masters[0]
// Get the MySQL database name of the tablet.
keyspaceAndShard := topoproto.KeyspaceShardString(si.Keyspace(), si.ShardName())
scw.destinationDbNames[keyspaceAndShard] = topoproto.TabletDbName(master.Tablet)
// TODO(mberlin): Verify on the destination master that the
// _vt.blp_checkpoint table has the latest schema.
scw.wr.Logger().Infof("Using tablet %v as destination master for %v/%v", topoproto.TabletAliasString(master.Tablet.Alias), si.Keyspace(), si.ShardName())
}
scw.wr.Logger().Infof("NOTE: The used master of a destination shard might change over the course of the copy e.g. due to a reparent. The HealthCheck module will track and log master changes and any error message will always refer the actually used master address.")
return nil
}
示例2: Run
// Run is part of the Task interface.
func (t *SplitCloneTask) Run(parameters map[string]string) ([]*automationpb.TaskContainer, string, error) {
// TODO(mberlin): Add parameters for the following options?
// '--source_reader_count', '1',
// '--destination_writer_count', '1',
args := []string{"SplitClone"}
if online := parameters["online"]; online != "" {
args = append(args, "--online="+online)
}
if offline := parameters["offline"]; offline != "" {
args = append(args, "--offline="+offline)
}
if excludeTables := parameters["exclude_tables"]; excludeTables != "" {
args = append(args, "--exclude_tables="+excludeTables)
}
if writeQueryMaxRows := parameters["write_query_max_rows"]; writeQueryMaxRows != "" {
args = append(args, "--write_query_max_rows="+writeQueryMaxRows)
}
if writeQueryMaxSize := parameters["write_query_max_size"]; writeQueryMaxSize != "" {
args = append(args, "--write_query_max_size="+writeQueryMaxSize)
}
if minHealthyRdonlyTablets := parameters["min_healthy_rdonly_tablets"]; minHealthyRdonlyTablets != "" {
args = append(args, "--min_healthy_rdonly_tablets="+minHealthyRdonlyTablets)
}
args = append(args, topoproto.KeyspaceShardString(parameters["keyspace"], parameters["source_shard"]))
output, err := ExecuteVtworker(context.TODO(), parameters["vtworker_endpoint"], args)
// TODO(mberlin): Remove explicit reset when vtworker supports it implicility.
if err == nil {
// Ignore output and error of the Reset.
ExecuteVtworker(context.TODO(), parameters["vtworker_endpoint"], []string{"Reset"})
}
return nil, output, err
}
示例3: shardsWithTablesSources
// shardsWithTablesSources returns all the shards that have SourceShards set
// to one value, with an array of Tables.
func shardsWithTablesSources(ctx context.Context, wr *wrangler.Wrangler) ([]map[string]string, error) {
shortCtx, cancel := context.WithTimeout(ctx, *remoteActionsTimeout)
keyspaces, err := wr.TopoServer().GetKeyspaces(shortCtx)
cancel()
if err != nil {
return nil, fmt.Errorf("failed to get list of keyspaces: %v", err)
}
wg := sync.WaitGroup{}
mu := sync.Mutex{} // protects result
result := make([]map[string]string, 0, len(keyspaces))
rec := concurrency.AllErrorRecorder{}
for _, keyspace := range keyspaces {
wg.Add(1)
go func(keyspace string) {
defer wg.Done()
shortCtx, cancel := context.WithTimeout(ctx, *remoteActionsTimeout)
shards, err := wr.TopoServer().GetShardNames(shortCtx, keyspace)
cancel()
if err != nil {
rec.RecordError(fmt.Errorf("failed to get list of shards for keyspace '%v': %v", keyspace, err))
return
}
for _, shard := range shards {
wg.Add(1)
go func(keyspace, shard string) {
defer wg.Done()
shortCtx, cancel := context.WithTimeout(ctx, *remoteActionsTimeout)
si, err := wr.TopoServer().GetShard(shortCtx, keyspace, shard)
cancel()
if err != nil {
rec.RecordError(fmt.Errorf("failed to get details for shard '%v': %v", topoproto.KeyspaceShardString(keyspace, shard), err))
return
}
if len(si.SourceShards) == 1 && len(si.SourceShards[0].Tables) > 0 {
mu.Lock()
result = append(result, map[string]string{
"Keyspace": keyspace,
"Shard": shard,
})
mu.Unlock()
}
}(keyspace, shard)
}
}(keyspace)
}
wg.Wait()
if rec.HasErrors() {
return nil, rec.Error()
}
if len(result) == 0 {
return nil, fmt.Errorf("there are no shards with SourceShards")
}
return result, nil
}
示例4: Run
// Run is part of the Task interface.
func (t *VerticalSplitDiffTask) Run(parameters map[string]string) ([]*automationpb.TaskContainer, string, error) {
args := []string{"VerticalSplitDiff"}
args = append(args, topoproto.KeyspaceShardString(parameters["dest_keyspace"], parameters["shard"]))
output, err := ExecuteVtworker(context.TODO(), parameters["vtworker_endpoint"], args)
// TODO(mberlin): Remove explicit reset when vtworker supports it implicility.
if err == nil {
// Ignore output and error of the Reset.
ExecuteVtworker(context.TODO(), parameters["vtworker_endpoint"], []string{"Reset"})
}
return nil, output, err
}
示例5: Run
// Run is part of the Task interface.
func (t *MigrateServedTypesTask) Run(parameters map[string]string) ([]*automationpb.TaskContainer, string, error) {
args := []string{"MigrateServedTypes"}
if cells := parameters["cells"]; cells != "" {
args = append(args, "--cells="+cells)
}
if reverse := parameters["reverse"]; reverse != "" {
args = append(args, "--reverse="+reverse)
}
args = append(args,
topoproto.KeyspaceShardString(parameters["keyspace"], parameters["source_shard"]),
parameters["type"])
output, err := ExecuteVtctl(context.TODO(), parameters["vtctld_endpoint"], args)
return nil, output, err
}
示例6: Run
// Run is part of the Task interface.
func (t *VerticalSplitDiffTask) Run(parameters map[string]string) ([]*automationpb.TaskContainer, string, error) {
// Run a "Reset" first to clear the state of a previous finished command.
// This reset is best effort. We ignore the output and error of it.
// TODO(mberlin): Remove explicit reset when vtworker supports it implicility.
ExecuteVtworker(context.TODO(), parameters["vtworker_endpoint"], []string{"Reset"})
args := []string{"VerticalSplitDiff"}
if minHealthyRdonlyTablets := parameters["min_healthy_rdonly_tablets"]; minHealthyRdonlyTablets != "" {
args = append(args, "--min_healthy_rdonly_tablets="+minHealthyRdonlyTablets)
}
args = append(args, topoproto.KeyspaceShardString(parameters["dest_keyspace"], parameters["shard"]))
output, err := ExecuteVtworker(context.TODO(), parameters["vtworker_endpoint"], args)
return nil, output, err
}
示例7: createThrottlers
func (scw *SplitCloneWorker) createThrottlers() error {
scw.throttlersMu.Lock()
defer scw.throttlersMu.Unlock()
for _, si := range scw.destinationShards {
// Set up the throttler for each destination shard.
keyspaceAndShard := topoproto.KeyspaceShardString(si.Keyspace(), si.ShardName())
t, err := throttler.NewThrottler(keyspaceAndShard, "transactions", scw.destinationWriterCount, scw.maxTPS, scw.maxReplicationLag)
if err != nil {
return fmt.Errorf("cannot instantiate throttler: %v", err)
}
scw.throttlers[keyspaceAndShard] = t
}
return nil
}
示例8: Run
// Run is part of the Task interface.
func (t *VerticalSplitCloneTask) Run(parameters map[string]string) ([]*automationpb.TaskContainer, string, error) {
// TODO(mberlin): Add parameters for the following options?
// '--source_reader_count', '1',
// '--destination_pack_count', '1',
// '--destination_writer_count', '1',
args := []string{"VerticalSplitClone"}
args = append(args, "--tables="+parameters["tables"])
args = append(args, topoproto.KeyspaceShardString(parameters["dest_keyspace"], parameters["shard"]))
output, err := ExecuteVtworker(context.TODO(), parameters["vtworker_endpoint"], args)
// TODO(mberlin): Remove explicit reset when vtworker supports it implicility.
if err == nil {
// Ignore output and error of the Reset.
ExecuteVtworker(context.TODO(), parameters["vtworker_endpoint"], []string{"Reset"})
}
return nil, output, err
}
示例9: Run
// Run is part of the Task interface.
func (t *SplitCloneTask) Run(parameters map[string]string) ([]*automationpb.TaskContainer, string, error) {
// Run a "Reset" first to clear the state of a previous finished command.
// This reset is best effort. We ignore the output and error of it.
// TODO(mberlin): Remove explicit reset when vtworker supports it implicility.
ExecuteVtworker(context.TODO(), parameters["vtworker_endpoint"], []string{"Reset"})
// TODO(mberlin): Add parameters for the following options?
// '--source_reader_count', '1',
// '--destination_writer_count', '1',
args := []string{"SplitClone"}
if online := parameters["online"]; online != "" {
args = append(args, "--online="+online)
}
if offline := parameters["offline"]; offline != "" {
args = append(args, "--offline="+offline)
}
if excludeTables := parameters["exclude_tables"]; excludeTables != "" {
args = append(args, "--exclude_tables="+excludeTables)
}
if chunkCount := parameters["chunk_count"]; chunkCount != "" {
args = append(args, "--chunk_count="+chunkCount)
}
if minRowsPerChunk := parameters["min_rows_per_chunk"]; minRowsPerChunk != "" {
args = append(args, "--min_rows_per_chunk="+minRowsPerChunk)
}
if writeQueryMaxRows := parameters["write_query_max_rows"]; writeQueryMaxRows != "" {
args = append(args, "--write_query_max_rows="+writeQueryMaxRows)
}
if writeQueryMaxSize := parameters["write_query_max_size"]; writeQueryMaxSize != "" {
args = append(args, "--write_query_max_size="+writeQueryMaxSize)
}
if minHealthyRdonlyTablets := parameters["min_healthy_rdonly_tablets"]; minHealthyRdonlyTablets != "" {
args = append(args, "--min_healthy_rdonly_tablets="+minHealthyRdonlyTablets)
}
if maxTPS := parameters["max_tps"]; maxTPS != "" {
args = append(args, "--max_tps="+maxTPS)
}
if maxReplicationLag := parameters["max_replication_lag"]; maxReplicationLag != "" {
args = append(args, "--max_replication_lag="+maxReplicationLag)
}
args = append(args, topoproto.KeyspaceShardString(parameters["keyspace"], parameters["source_shard"]))
output, err := ExecuteVtworker(context.TODO(), parameters["vtworker_endpoint"], args)
return nil, output, err
}
示例10: Run
// Run is part of the Task interface.
func (t *SplitDiffTask) Run(parameters map[string]string) ([]*automationpb.TaskContainer, string, error) {
args := []string{"SplitDiff"}
if excludeTables := parameters["exclude_tables"]; excludeTables != "" {
args = append(args, "--exclude_tables="+excludeTables)
}
if minHealthyRdonlyTablets := parameters["min_healthy_rdonly_tablets"]; minHealthyRdonlyTablets != "" {
args = append(args, "--min_healthy_rdonly_tablets="+minHealthyRdonlyTablets)
}
args = append(args, topoproto.KeyspaceShardString(parameters["keyspace"], parameters["dest_shard"]))
output, err := ExecuteVtworker(context.TODO(), parameters["vtworker_endpoint"], args)
// TODO(mberlin): Remove explicit reset when vtworker supports it implicility.
if err == nil {
// Ignore output and error of the Reset.
ExecuteVtworker(context.TODO(), parameters["vtworker_endpoint"], []string{"Reset"})
}
return nil, output, err
}
示例11: Run
// Run is part of the Task interface.
func (t *VerticalSplitCloneTask) Run(parameters map[string]string) ([]*automationpb.TaskContainer, string, error) {
// TODO(mberlin): Add parameters for the following options?
// '--source_reader_count', '1',
// '--destination_writer_count', '1',
args := []string{"VerticalSplitClone"}
args = append(args, "--tables="+parameters["tables"])
if online := parameters["online"]; online != "" {
args = append(args, "--online="+online)
}
if offline := parameters["offline"]; offline != "" {
args = append(args, "--offline="+offline)
}
if chunkCount := parameters["chunk_count"]; chunkCount != "" {
args = append(args, "--chunk_count="+chunkCount)
}
if minRowsPerChunk := parameters["min_rows_per_chunk"]; minRowsPerChunk != "" {
args = append(args, "--min_rows_per_chunk="+minRowsPerChunk)
}
if writeQueryMaxRows := parameters["write_query_max_rows"]; writeQueryMaxRows != "" {
args = append(args, "--write_query_max_rows="+writeQueryMaxRows)
}
if writeQueryMaxSize := parameters["write_query_max_size"]; writeQueryMaxSize != "" {
args = append(args, "--write_query_max_size="+writeQueryMaxSize)
}
if minHealthyRdonlyTablets := parameters["min_healthy_rdonly_tablets"]; minHealthyRdonlyTablets != "" {
args = append(args, "--min_healthy_rdonly_tablets="+minHealthyRdonlyTablets)
}
if maxTPS := parameters["max_tps"]; maxTPS != "" {
args = append(args, "--max_tps="+maxTPS)
}
if maxReplicationLag := parameters["max_replication_lag"]; maxReplicationLag != "" {
args = append(args, "--max_replication_lag="+maxReplicationLag)
}
args = append(args, topoproto.KeyspaceShardString(parameters["dest_keyspace"], parameters["shard"]))
output, err := ExecuteVtworker(context.TODO(), parameters["vtworker_endpoint"], args)
// TODO(mberlin): Remove explicit reset when vtworker supports it implicility.
if err == nil {
// Ignore output and error of the Reset.
ExecuteVtworker(context.TODO(), parameters["vtworker_endpoint"], []string{"Reset"})
}
return nil, output, err
}
示例12: findTargets
// findTargets phase:
// - find one rdonly in the source shard
// - mark it as 'worker' pointing back to us
// - get the aliases of all the targets
func (vscw *VerticalSplitCloneWorker) findTargets(ctx context.Context) error {
vscw.setState(WorkerStateFindTargets)
// find an appropriate tablet in the source shard
var err error
vscw.sourceAlias, err = FindWorkerTablet(ctx, vscw.wr, vscw.cleaner, nil /* tsc */, vscw.cell, vscw.sourceKeyspace, "0", vscw.minHealthyRdonlyTablets)
if err != nil {
return fmt.Errorf("FindWorkerTablet() failed for %v/%v/0: %v", vscw.cell, vscw.sourceKeyspace, err)
}
vscw.wr.Logger().Infof("Using tablet %v as the source", topoproto.TabletAliasString(vscw.sourceAlias))
// get the tablet info for it
shortCtx, cancel := context.WithTimeout(ctx, *remoteActionsTimeout)
ti, err := vscw.wr.TopoServer().GetTablet(shortCtx, vscw.sourceAlias)
cancel()
if err != nil {
return fmt.Errorf("cannot read tablet %v: %v", topoproto.TabletAliasString(vscw.sourceAlias), err)
}
vscw.sourceTablet = ti.Tablet
// stop replication on it
shortCtx, cancel = context.WithTimeout(ctx, *remoteActionsTimeout)
err = vscw.wr.TabletManagerClient().StopSlave(shortCtx, vscw.sourceTablet)
cancel()
if err != nil {
return fmt.Errorf("cannot stop replication on tablet %v", topoproto.TabletAliasString(vscw.sourceAlias))
}
wrangler.RecordStartSlaveAction(vscw.cleaner, vscw.sourceTablet)
// Initialize healthcheck and add destination shards to it.
vscw.healthCheck = discovery.NewHealthCheck(*remoteActionsTimeout, *healthcheckRetryDelay, *healthCheckTimeout)
vscw.tsc = discovery.NewTabletStatsCache(vscw.healthCheck, vscw.cell)
watcher := discovery.NewShardReplicationWatcher(vscw.wr.TopoServer(), vscw.healthCheck,
vscw.cell, vscw.destinationKeyspace, vscw.destinationShard,
*healthCheckTopologyRefresh, discovery.DefaultTopoReadConcurrency)
vscw.destinationShardWatchers = append(vscw.destinationShardWatchers, watcher)
// Make sure we find a master for each destination shard and log it.
vscw.wr.Logger().Infof("Finding a MASTER tablet for each destination shard...")
waitCtx, waitCancel := context.WithTimeout(ctx, *waitForHealthyTabletsTimeout)
defer waitCancel()
if err := vscw.tsc.WaitForTablets(waitCtx, vscw.cell, vscw.destinationKeyspace, vscw.destinationShard, []topodatapb.TabletType{topodatapb.TabletType_MASTER}); err != nil {
return fmt.Errorf("cannot find MASTER tablet for destination shard for %v/%v (in cell: %v): %v", vscw.destinationKeyspace, vscw.destinationShard, vscw.cell, err)
}
masters := vscw.tsc.GetHealthyTabletStats(vscw.destinationKeyspace, vscw.destinationShard, topodatapb.TabletType_MASTER)
if len(masters) == 0 {
return fmt.Errorf("cannot find MASTER tablet for destination shard for %v/%v (in cell: %v) in HealthCheck: empty TabletStats list", vscw.destinationKeyspace, vscw.destinationShard, vscw.cell)
}
master := masters[0]
// Get the MySQL database name of the tablet.
keyspaceAndShard := topoproto.KeyspaceShardString(vscw.destinationKeyspace, vscw.destinationShard)
vscw.destinationDbNames[keyspaceAndShard] = topoproto.TabletDbName(master.Tablet)
// TODO(mberlin): Verify on the destination master that the
// _vt.blp_checkpoint table has the latest schema.
vscw.wr.Logger().Infof("Using tablet %v as destination master for %v/%v", topoproto.TabletAliasString(master.Tablet.Alias), vscw.destinationKeyspace, vscw.destinationShard)
vscw.wr.Logger().Infof("NOTE: The used master of a destination shard might change over the course of the copy e.g. due to a reparent. The HealthCheck module will track and log master changes and any error message will always refer the actually used master address.")
return nil
}
示例13: description
func (p *shardTabletProvider) description() string {
return topoproto.KeyspaceShardString(p.keyspace, p.shard)
}
示例14: copy
// copy phase:
// - copy the data from source tablets to destination masters (with replication on)
// Assumes that the schema has already been created on each destination tablet
// (probably from vtctl's CopySchemaShard)
func (scw *LegacySplitCloneWorker) copy(ctx context.Context) error {
scw.setState(WorkerStateCloneOffline)
start := time.Now()
defer func() {
statsStateDurationsNs.Set(string(WorkerStateCloneOffline), time.Now().Sub(start).Nanoseconds())
}()
// get source schema from the first shard
// TODO(alainjobart): for now, we assume the schema is compatible
// on all source shards. Furthermore, we estimate the number of rows
// in each source shard for each table to be about the same
// (rowCount is used to estimate an ETA)
shortCtx, cancel := context.WithTimeout(ctx, *remoteActionsTimeout)
sourceSchemaDefinition, err := scw.wr.GetSchema(shortCtx, scw.sourceAliases[0], nil, scw.excludeTables, false /* includeViews */)
cancel()
if err != nil {
return fmt.Errorf("cannot get schema from source %v: %v", topoproto.TabletAliasString(scw.sourceAliases[0]), err)
}
if len(sourceSchemaDefinition.TableDefinitions) == 0 {
return fmt.Errorf("no tables matching the table filter in tablet %v", topoproto.TabletAliasString(scw.sourceAliases[0]))
}
for _, td := range sourceSchemaDefinition.TableDefinitions {
if len(td.Columns) == 0 {
return fmt.Errorf("schema for table %v has no columns", td.Name)
}
}
scw.wr.Logger().Infof("Source tablet 0 has %v tables to copy", len(sourceSchemaDefinition.TableDefinitions))
scw.tableStatusList.initialize(sourceSchemaDefinition)
// In parallel, setup the channels to send SQL data chunks to for each destination tablet:
//
// mu protects the context for cancelation, and firstError
mu := sync.Mutex{}
var firstError error
ctx, cancelCopy := context.WithCancel(ctx)
processError := func(format string, args ...interface{}) {
scw.wr.Logger().Errorf(format, args...)
mu.Lock()
if firstError == nil {
firstError = fmt.Errorf(format, args...)
cancelCopy()
}
mu.Unlock()
}
insertChannels := make([]chan string, len(scw.destinationShards))
destinationWaitGroup := sync.WaitGroup{}
for shardIndex, si := range scw.destinationShards {
// we create one channel per destination tablet. It
// is sized to have a buffer of a maximum of
// destinationWriterCount * 2 items, to hopefully
// always have data. We then have
// destinationWriterCount go routines reading from it.
insertChannels[shardIndex] = make(chan string, scw.destinationWriterCount*2)
go func(keyspace, shard string, insertChannel chan string) {
for j := 0; j < scw.destinationWriterCount; j++ {
destinationWaitGroup.Add(1)
go func(threadID int) {
defer destinationWaitGroup.Done()
keyspaceAndShard := topoproto.KeyspaceShardString(keyspace, shard)
throttler := scw.destinationThrottlers[keyspaceAndShard]
defer throttler.ThreadFinished(threadID)
executor := newExecutor(scw.wr, scw.tsc, throttler, keyspace, shard, threadID)
if err := executor.fetchLoop(ctx, insertChannel); err != nil {
processError("executer.FetchLoop failed: %v", err)
}
}(j)
}
}(si.Keyspace(), si.ShardName(), insertChannels[shardIndex])
}
// read the vschema if needed
var keyspaceSchema *vindexes.KeyspaceSchema
if *useV3ReshardingMode {
kschema, err := scw.wr.TopoServer().GetVSchema(ctx, scw.keyspace)
if err != nil {
return fmt.Errorf("cannot load VSchema for keyspace %v: %v", scw.keyspace, err)
}
if kschema == nil {
return fmt.Errorf("no VSchema for keyspace %v", scw.keyspace)
}
keyspaceSchema, err = vindexes.BuildKeyspaceSchema(kschema, scw.keyspace)
if err != nil {
return fmt.Errorf("cannot build vschema for keyspace %v: %v", scw.keyspace, err)
}
}
// Now for each table, read data chunks and send them to all
// insertChannels
sourceWaitGroup := sync.WaitGroup{}
for shardIndex := range scw.sourceShards {
//.........这里部分代码省略.........
示例15: findTargets
// findTargets phase:
// - find one rdonly in the source shard
// - mark it as 'worker' pointing back to us
// - get the aliases of all the targets
func (scw *LegacySplitCloneWorker) findTargets(ctx context.Context) error {
scw.setState(WorkerStateFindTargets)
var err error
// find an appropriate tablet in the source shards
scw.sourceAliases = make([]*topodatapb.TabletAlias, len(scw.sourceShards))
for i, si := range scw.sourceShards {
scw.sourceAliases[i], err = FindWorkerTablet(ctx, scw.wr, scw.cleaner, scw.tsc, scw.cell, si.Keyspace(), si.ShardName(), scw.minHealthyRdonlyTablets)
if err != nil {
return fmt.Errorf("FindWorkerTablet() failed for %v/%v/%v: %v", scw.cell, si.Keyspace(), si.ShardName(), err)
}
scw.wr.Logger().Infof("Using tablet %v as source for %v/%v", topoproto.TabletAliasString(scw.sourceAliases[i]), si.Keyspace(), si.ShardName())
}
// get the tablet info for them, and stop their replication
scw.sourceTablets = make([]*topodatapb.Tablet, len(scw.sourceAliases))
for i, alias := range scw.sourceAliases {
shortCtx, cancel := context.WithTimeout(ctx, *remoteActionsTimeout)
ti, err := scw.wr.TopoServer().GetTablet(shortCtx, alias)
cancel()
if err != nil {
return fmt.Errorf("cannot read tablet %v: %v", topoproto.TabletAliasString(alias), err)
}
scw.sourceTablets[i] = ti.Tablet
shortCtx, cancel = context.WithTimeout(ctx, *remoteActionsTimeout)
err = scw.wr.TabletManagerClient().StopSlave(shortCtx, scw.sourceTablets[i])
cancel()
if err != nil {
return fmt.Errorf("cannot stop replication on tablet %v", topoproto.TabletAliasString(alias))
}
wrangler.RecordStartSlaveAction(scw.cleaner, scw.sourceTablets[i])
}
// Initialize healthcheck and add destination shards to it.
scw.healthCheck = discovery.NewHealthCheck(*remoteActionsTimeout, *healthcheckRetryDelay, *healthCheckTimeout)
scw.tsc = discovery.NewTabletStatsCache(scw.healthCheck, scw.cell)
for _, si := range scw.destinationShards {
watcher := discovery.NewShardReplicationWatcher(scw.wr.TopoServer(), scw.healthCheck,
scw.cell, si.Keyspace(), si.ShardName(),
*healthCheckTopologyRefresh, discovery.DefaultTopoReadConcurrency)
scw.destinationShardWatchers = append(scw.destinationShardWatchers, watcher)
}
// Make sure we find a master for each destination shard and log it.
scw.wr.Logger().Infof("Finding a MASTER tablet for each destination shard...")
for _, si := range scw.destinationShards {
waitCtx, waitCancel := context.WithTimeout(ctx, 10*time.Second)
defer waitCancel()
if err := scw.tsc.WaitForTablets(waitCtx, scw.cell, si.Keyspace(), si.ShardName(), []topodatapb.TabletType{topodatapb.TabletType_MASTER}); err != nil {
return fmt.Errorf("cannot find MASTER tablet for destination shard for %v/%v: %v", si.Keyspace(), si.ShardName(), err)
}
masters := scw.tsc.GetHealthyTabletStats(si.Keyspace(), si.ShardName(), topodatapb.TabletType_MASTER)
if len(masters) == 0 {
return fmt.Errorf("cannot find MASTER tablet for destination shard for %v/%v in HealthCheck: empty TabletStats list", si.Keyspace(), si.ShardName())
}
master := masters[0]
// Get the MySQL database name of the tablet.
shortCtx, cancel := context.WithTimeout(ctx, *remoteActionsTimeout)
ti, err := scw.wr.TopoServer().GetTablet(shortCtx, master.Tablet.Alias)
cancel()
if err != nil {
return fmt.Errorf("cannot get the TabletInfo for destination master (%v) to find out its db name: %v", topoproto.TabletAliasString(master.Tablet.Alias), err)
}
keyspaceAndShard := topoproto.KeyspaceShardString(si.Keyspace(), si.ShardName())
scw.destinationDbNames[keyspaceAndShard] = ti.DbName()
// TODO(mberlin): Verify on the destination master that the
// _vt.blp_checkpoint table has the latest schema.
scw.wr.Logger().Infof("Using tablet %v as destination master for %v/%v", topoproto.TabletAliasString(master.Tablet.Alias), si.Keyspace(), si.ShardName())
}
scw.wr.Logger().Infof("NOTE: The used master of a destination shard might change over the course of the copy e.g. due to a reparent. The HealthCheck module will track and log master changes and any error message will always refer the actually used master address.")
// Set up the throttler for each destination shard.
for _, si := range scw.destinationShards {
keyspaceAndShard := topoproto.KeyspaceShardString(si.Keyspace(), si.ShardName())
t, err := throttler.NewThrottler(
keyspaceAndShard, "transactions", scw.destinationWriterCount, scw.maxTPS, throttler.ReplicationLagModuleDisabled)
if err != nil {
return fmt.Errorf("cannot instantiate throttler: %v", err)
}
scw.destinationThrottlers[keyspaceAndShard] = t
}
return nil
}