示例#1
0
// This maps a list of keyranges to shard names.
func resolveKeyRangeToShards(topoServer SrvTopoServer, cell, keyspace string, tabletType topo.TabletType, kr key.KeyRange) ([]string, error) {
	srvKeyspace, err := topoServer.GetSrvKeyspace(cell, keyspace)
	if err != nil {
		return nil, fmt.Errorf("Error in reading the keyspace %v", err)
	}

	tabletTypePartition, ok := srvKeyspace.Partitions[tabletType]
	if !ok {
		return nil, fmt.Errorf("No shards available for tablet type '%v' in keyspace '%v'", tabletType, keyspace)
	}

	topo.SrvShardArray(tabletTypePartition.Shards).Sort()

	shards := make([]string, 0, 1)
	if !kr.IsPartial() {
		for j := 0; j < len(tabletTypePartition.Shards); j++ {
			shards = append(shards, tabletTypePartition.Shards[j].ShardName())
		}
		return shards, nil
	}
	for j := 0; j < len(tabletTypePartition.Shards); j++ {
		shard := tabletTypePartition.Shards[j]
		if key.KeyRangesIntersect(kr, shard.KeyRange) {
			shards = append(shards, shard.ShardName())
		}
		if kr.End != key.MaxKey && kr.End < shard.KeyRange.Start {
			break
		}
	}
	return shards, nil
}
示例#2
0
// CreateShard creates a new shard and tries to fill in the right information.
func CreateShard(ts Server, keyspace, shard string) error {

	name, keyRange, err := ValidateShardName(shard)
	if err != nil {
		return err
	}
	s := &Shard{KeyRange: keyRange}

	// start the shard with all serving types. If it overlaps with
	// other shards for some serving types, remove them.
	servingTypes := map[TabletType]bool{
		TYPE_MASTER:  true,
		TYPE_REPLICA: true,
		TYPE_RDONLY:  true,
	}
	sis, err := FindAllShardsInKeyspace(ts, keyspace)
	if err != nil && err != ErrNoNode {
		return err
	}
	for _, si := range sis {
		if key.KeyRangesIntersect(si.KeyRange, keyRange) {
			for _, t := range si.ServedTypes {
				delete(servingTypes, t)
			}
		}
	}
	s.ServedTypes = make([]TabletType, 0, len(servingTypes))
	for st := range servingTypes {
		s.ServedTypes = append(s.ServedTypes, st)
	}

	return ts.CreateShard(keyspace, name, s)
}
示例#3
0
文件: shard.go 项目: plobsing/vitess
// CreateShard creates a new shard and tries to fill in the right information.
func CreateShard(ts Server, keyspace, shard string) error {

	name, keyRange, err := ValidateShardName(shard)
	if err != nil {
		return err
	}

	// start the shard with all serving types. If it overlaps with
	// other shards for some serving types, remove them.
	s := &Shard{
		KeyRange: keyRange,
		ServedTypesMap: map[TabletType]*ShardServedType{
			TYPE_MASTER:  &ShardServedType{},
			TYPE_REPLICA: &ShardServedType{},
			TYPE_RDONLY:  &ShardServedType{},
		},
	}

	sis, err := FindAllShardsInKeyspace(ts, keyspace)
	if err != nil && err != ErrNoNode {
		return err
	}
	for _, si := range sis {
		if key.KeyRangesIntersect(si.KeyRange, keyRange) {
			for t, _ := range si.ServedTypesMap {
				delete(s.ServedTypesMap, t)
			}
		}
	}
	if len(s.ServedTypesMap) == 0 {
		s.ServedTypesMap = nil
	}

	return ts.CreateShard(keyspace, name, s)
}
示例#4
0
// intersect returns true if the provided shard intersect with any shard
// in the destination array
func intersect(si *topo.ShardInfo, allShards []*topo.ShardInfo) bool {
	for _, shard := range allShards {
		if key.KeyRangesIntersect(si.KeyRange, shard.KeyRange) {
			return true
		}
	}
	return false
}
示例#5
0
// findIntersectingShard will go through the map and take the first
// entry in there that intersect with the source array, remove it from
// the map, and return it
func findIntersectingShard(shardMap map[string]*topo.ShardInfo, sourceArray []*topo.ShardInfo) *topo.ShardInfo {
	for name, si := range shardMap {
		for _, sourceShardInfo := range sourceArray {
			if key.KeyRangesIntersect(si.KeyRange, sourceShardInfo.KeyRange) {
				delete(shardMap, name)
				return si
			}
		}
	}
	return nil
}
示例#6
0
// This maps a list of keyranges to shard names.
func resolveKeyRangeToShards(allShards []*topodatapb.ShardReference, matches map[string]bool, kr *topodatapb.KeyRange) {
	if !key.KeyRangeIsPartial(kr) {
		for _, shard := range allShards {
			matches[shard.Name] = true
		}
		return
	}
	for _, shard := range allShards {
		if key.KeyRangesIntersect(kr, shard.KeyRange) {
			matches[shard.Name] = true
		}
	}
}
示例#7
0
// CreateShard creates a new shard and tries to fill in the right information.
// This should be called while holding the keyspace lock for the shard.
// (call topotools.CreateShard to do that for you).
// In unit tests (that are not parallel), this function can be called directly.
func (ts Server) CreateShard(ctx context.Context, keyspace, shard string) error {
	name, keyRange, err := ValidateShardName(shard)
	if err != nil {
		return err
	}

	// start the shard with all serving types. If it overlaps with
	// other shards for some serving types, remove them.
	servedTypes := map[topodatapb.TabletType]bool{
		topodatapb.TabletType_MASTER:  true,
		topodatapb.TabletType_REPLICA: true,
		topodatapb.TabletType_RDONLY:  true,
	}
	value := &topodatapb.Shard{
		KeyRange: keyRange,
	}

	if IsShardUsingRangeBasedSharding(name) {
		// if we are using range-based sharding, we don't want
		// overlapping shards to all serve and confuse the clients.
		sis, err := ts.FindAllShardsInKeyspace(ctx, keyspace)
		if err != nil && err != ErrNoNode {
			return err
		}
		for _, si := range sis {
			if si.KeyRange == nil || key.KeyRangesIntersect(si.KeyRange, keyRange) {
				for _, st := range si.ServedTypes {
					delete(servedTypes, st.TabletType)
				}
			}
		}
	}

	for st := range servedTypes {
		value.ServedTypes = append(value.ServedTypes, &topodatapb.Shard_ServedType{
			TabletType: st,
		})
	}

	if err := ts.Impl.CreateShard(ctx, keyspace, name, value); err != nil {
		return err
	}

	event.Dispatch(&events.ShardChange{
		KeyspaceName: keyspace,
		ShardName:    shard,
		Shard:        value,
		Status:       "created",
	})
	return nil
}
示例#8
0
// This maps a list of keyranges to shard names.
func resolveKeyRangeToShards(allShards []*pb.ShardReference, kr *pb.KeyRange) ([]string, error) {
	shards := make([]string, 0, 1)

	if !key.KeyRangeIsPartial(kr) {
		for j := 0; j < len(allShards); j++ {
			shards = append(shards, allShards[j].Name)
		}
		return shards, nil
	}
	for j := 0; j < len(allShards); j++ {
		shard := allShards[j]
		if key.KeyRangesIntersect(kr, shard.KeyRange) {
			shards = append(shards, shard.Name)
		}
	}
	return shards, nil
}
示例#9
0
// This maps a list of keyranges to shard names.
func resolveKeyRangeToShards(allShards []topo.SrvShard, kr key.KeyRange) ([]string, error) {
	shards := make([]string, 0, 1)

	if !kr.IsPartial() {
		for j := 0; j < len(allShards); j++ {
			shards = append(shards, allShards[j].ShardName())
		}
		return shards, nil
	}
	for j := 0; j < len(allShards); j++ {
		shard := allShards[j]
		if key.KeyRangesIntersect(kr, shard.KeyRange) {
			shards = append(shards, shard.ShardName())
		}
	}
	return shards, nil
}
示例#10
0
// This maps a list of keyranges to shard names.
func resolveKeyRangeToShards(allShards []topo.SrvShard, kr key.KeyRange) ([]string, error) {
	shards := make([]string, 0, 1)
	topo.SrvShardArray(allShards).Sort()

	if !kr.IsPartial() {
		for j := 0; j < len(allShards); j++ {
			shards = append(shards, allShards[j].ShardName())
		}
		return shards, nil
	}
	for j := 0; j < len(allShards); j++ {
		shard := allShards[j]
		if key.KeyRangesIntersect(kr, shard.KeyRange) {
			shards = append(shards, shard.ShardName())
		}
		if kr.End != key.MaxKey && kr.End < shard.KeyRange.Start {
			break
		}
	}
	return shards, nil
}
示例#11
0
// CreateShard creates a new shard and tries to fill in the right information.
// This should be called while holding the keyspace lock for the shard.
// (call topotools.CreateShard to do that for you).
// In unit tests (that are not parallel), this function can be called directly.
func CreateShard(ctx context.Context, ts Server, keyspace, shard string) error {
	name, keyRange, err := ValidateShardName(shard)
	if err != nil {
		return err
	}

	// start the shard with all serving types. If it overlaps with
	// other shards for some serving types, remove them.
	s := &Shard{
		KeyRange: keyRange,
		ServedTypesMap: map[TabletType]*ShardServedType{
			TYPE_MASTER:  &ShardServedType{},
			TYPE_REPLICA: &ShardServedType{},
			TYPE_RDONLY:  &ShardServedType{},
		},
	}

	if IsShardUsingRangeBasedSharding(name) {
		// if we are using range-based sharding, we don't want
		// overlapping shards to all serve and confuse the clients.
		sis, err := FindAllShardsInKeyspace(ctx, ts, keyspace)
		if err != nil && err != ErrNoNode {
			return err
		}
		for _, si := range sis {
			if key.KeyRangesIntersect(si.KeyRange, keyRange) {
				for t := range si.ServedTypesMap {
					delete(s.ServedTypesMap, t)
				}
			}
		}
		if len(s.ServedTypesMap) == 0 {
			s.ServedTypesMap = nil
		}
	}

	return ts.CreateShard(ctx, keyspace, name, s)
}
示例#12
0
// getConn returns the right l2VTGateConn for a given keyspace / shard.
func (lg *l2VTGateGateway) getConn(keyspace, shard string) (*l2VTGateConn, error) {
	lg.mu.RLock()
	defer lg.mu.RUnlock()

	canonical, kr, err := topo.ValidateShardName(shard)
	if err != nil {
		return nil, fmt.Errorf("invalid shard name: %v", shard)
	}

	for _, c := range lg.connMap[keyspace] {
		if canonical == c.shard {
			// Exact match (probably a non-sharded keyspace).
			return c, nil
		}
		if key.KeyRangesIntersect(kr, c.keyRange) {
			// There is overlap, we can just send to the destination.
			// FIXME(alainjobart) if canonical is not entirely covered by l2vtgate,
			// this is probably an error. We probably want key.KeyRangeIncludes(), NYI.
			return c, nil
		}
	}

	return nil, fmt.Errorf("no configured destination for %v/%v", keyspace, shard)
}