예제 #1
0
파일: prefix.go 프로젝트: nkhuyu/cockroach
// MatchByPrefix returns the longest matching PrefixConfig. If the key
// specified does not match an existing prefix, a panic will
// result. Based on the comments in NewPrefixConfigMap, that example
// will have a final list of PrefixConfig entries which look like:
//
//   "/":          config1
//   "/db1":       config2
//   "/db1/table": config3
//   "/db1/tablf": config2
//   "/db2":       config1
//   "/db3":       config4
//   "/db4":       config1
//
// To find the longest matching prefix, we take the lower bound of the
// specified key.
func (p PrefixConfigMap) MatchByPrefix(key proto.Key) *PrefixConfig {
	n := sort.Search(len(p), func(i int) bool {
		return key.Compare(p[i].Prefix) < 0
	})
	if n == 0 || n > len(p) {
		panic("should never match a key outside of default range")
	}
	// If the matched prefix config is already canonical, return it immediately.
	pc := p[n-1]
	if pc.Canonical == nil {
		return pc
	}
	// Otherwise, search for the canonical prefix config.
	n = sort.Search(len(p), func(i int) bool {
		return pc.Canonical.Compare(p[i].Prefix) <= 0
	})
	// Should find an exact match every time.
	if n >= len(p) || !pc.Canonical.Equal(p[n].Prefix) {
		panic(fmt.Sprintf("canonical lookup for key %q failed", string(pc.Canonical)))
	}
	return p[n]
}
예제 #2
0
파일: prefix.go 프로젝트: nkhuyu/cockroach
// VisitPrefixes invokes the visitor function for each prefix overlapped
// by the specified key range [start, end). If visitor returns done=true
// or an error, the visitation is halted.
func (p PrefixConfigMap) VisitPrefixes(start, end proto.Key,
	visitor func(start, end proto.Key, config gogoproto.Message) (bool, error)) error {
	comp := start.Compare(end)
	if comp > 0 {
		return util.Errorf("start key %q not less than or equal to end key %q", start, end)
	}
	startIdx := sort.Search(len(p), func(i int) bool {
		return start.Compare(p[i].Prefix) < 0
	})
	// Common case of start == end.
	endIdx := startIdx
	if comp != 0 {
		endIdx = sort.Search(len(p), func(i int) bool {
			return end.Compare(p[i].Prefix) < 0
		})
	}

	if startIdx > len(p) || endIdx > len(p) {
		return util.Errorf("start and/or end keys (%q, %q) fall outside prefix range; "+
			"startIdx: %d, endIdx: %d, len(p): %d", start, end, startIdx, endIdx, len(p))
	}

	if startIdx == endIdx {
		_, err := visitor(start, end, p[startIdx-1].Config)
		return err
	}
	for i := startIdx; i < endIdx; i++ {
		done, err := visitor(start, p[i].Prefix, p[i-1].Config)
		if done || err != nil {
			return err
		}
		if p[i].Prefix.Equal(end) {
			return nil
		}
		start = p[i].Prefix
	}
	done, err := visitor(start, end, p[endIdx-1].Config)
	if done || err != nil {
		return err
	}

	return nil
}