func (zkts *Server) UpdateKeyspace(ki *topo.KeyspaceInfo, existingVersion int64) (int64, error) { keyspacePath := path.Join(globalKeyspacesPath, ki.KeyspaceName()) data := jscfg.ToJson(ki.Keyspace) stat, err := zkts.zconn.Set(keyspacePath, data, int(existingVersion)) if err != nil { if zookeeper.IsError(err, zookeeper.ZNONODE) { err = topo.ErrNoNode } return -1, err } event.Dispatch(&events.KeyspaceChange{ KeyspaceInfo: *ki, Status: "updated", }) return int64(stat.Version()), nil }
// findCellsForRebuild will find all the cells in the given keyspace // and create an entry if the map for them func (wr *Wrangler) findCellsForRebuild(ki *topo.KeyspaceInfo, shardMap map[string]*topo.ShardInfo, cells []string, srvKeyspaceMap map[string]*topo.SrvKeyspace) { for _, si := range shardMap { for _, cell := range si.Cells { if !topo.InCellList(cell, cells) { continue } if _, ok := srvKeyspaceMap[cell]; !ok { srvKeyspaceMap[cell] = &topo.SrvKeyspace{ Shards: make([]topo.SrvShard, 0, 16), ShardingColumnName: ki.ShardingColumnName, ShardingColumnType: ki.ShardingColumnType, ServedFrom: ki.ComputeCellServedFrom(cell), SplitShardCount: ki.SplitShardCount, } } } } }
func (wr *Wrangler) migrateServedFrom(ki *topo.KeyspaceInfo, destinationShard *topo.ShardInfo, servedType topo.TabletType, cells []string, reverse bool) (err error) { // re-read and update keyspace info record ki, err = wr.ts.GetKeyspace(ki.KeyspaceName()) if err != nil { return err } if reverse { ki.UpdateServedFromMap(servedType, cells, destinationShard.SourceShards[0].Keyspace, false, nil) } else { ki.UpdateServedFromMap(servedType, cells, destinationShard.SourceShards[0].Keyspace, true, destinationShard.Cells) } // re-read and check the destination shard destinationShard, err = wr.ts.GetShard(destinationShard.Keyspace(), destinationShard.ShardName()) if err != nil { return err } if len(destinationShard.SourceShards) != 1 { return fmt.Errorf("Destination shard %v/%v is not a vertical split target", destinationShard.Keyspace(), destinationShard.ShardName()) } tables := destinationShard.SourceShards[0].Tables // read the source shard, we'll need its master, and we'll need to // update the blacklisted tables. var sourceShard *topo.ShardInfo sourceShard, err = wr.ts.GetShard(destinationShard.SourceShards[0].Keyspace, destinationShard.SourceShards[0].Shard) if err != nil { return err } ev := &events.MigrateServedFrom{ Keyspace: *ki, SourceShard: *sourceShard, DestinationShard: *destinationShard, ServedType: servedType, Reverse: reverse, } event.DispatchUpdate(ev, "start") defer func() { if err != nil { event.DispatchUpdate(ev, "failed: "+err.Error()) } }() if servedType == topo.TYPE_MASTER { err = wr.masterMigrateServedFrom(ki, sourceShard, destinationShard, tables, ev) } else { err = wr.replicaMigrateServedFrom(ki, sourceShard, destinationShard, servedType, cells, reverse, tables, ev) } event.DispatchUpdate(ev, "finished") return }
func (tee *Tee) UpdateKeyspace(ki *topo.KeyspaceInfo, existingVersion int64) (newVersion int64, err error) { if newVersion, err = tee.primary.UpdateKeyspace(ki, existingVersion); err != nil { // failed on primary, not updating secondary return } // if we have a mapping between keyspace version in first topo // and keyspace version in second topo, replace the version number. // if not, this will probably fail and log. tee.mu.Lock() kvm, ok := tee.keyspaceVersionMapping[ki.KeyspaceName()] if ok && kvm.readFromVersion == existingVersion { existingVersion = kvm.readFromSecondVersion delete(tee.keyspaceVersionMapping, ki.KeyspaceName()) } tee.mu.Unlock() if newVersion2, serr := tee.secondary.UpdateKeyspace(ki, existingVersion); serr != nil { // not critical enough to fail if serr == topo.ErrNoNode { // the keyspace doesn't exist on the secondary, let's // just create it if serr = tee.secondary.CreateKeyspace(ki.KeyspaceName(), ki.Keyspace); serr != nil { log.Warningf("secondary.CreateKeyspace(%v) failed (after UpdateKeyspace returned ErrNoNode): %v", ki.KeyspaceName(), serr) } else { log.Infof("secondary.UpdateKeyspace(%v) failed with ErrNoNode, CreateKeyspace then worked.", ki.KeyspaceName()) ki, gerr := tee.secondary.GetKeyspace(ki.KeyspaceName()) if gerr != nil { log.Warningf("Failed to re-read keyspace(%v) after creating it on secondary: %v", ki.KeyspaceName(), gerr) } else { tee.mu.Lock() tee.keyspaceVersionMapping[ki.KeyspaceName()] = versionMapping{ readFromVersion: newVersion, readFromSecondVersion: ki.Version(), } tee.mu.Unlock() } } } else { log.Warningf("secondary.UpdateKeyspace(%v) failed: %v", ki.KeyspaceName(), serr) } } else { tee.mu.Lock() tee.keyspaceVersionMapping[ki.KeyspaceName()] = versionMapping{ readFromVersion: newVersion, readFromSecondVersion: newVersion2, } tee.mu.Unlock() } return }