Ejemplo n.º 1
0
// mvccSeek seeks for the first key in db which has a k >= key and a version <=
// snapshot's version, returns kv.ErrNotExist if such key is not found. If exact
// is true, only k == key can be returned.
func (s *dbSnapshot) mvccSeek(key kv.Key, exact bool) (kv.Key, []byte, error) {
	// Key layout:
	// ...
	// Key_verMax      -- (1)
	// ...
	// Key_ver+1       -- (2)
	// Key_ver         -- (3)
	// Key_ver-1       -- (4)
	// ...
	// Key_0           -- (5)
	// NextKey_verMax  -- (6)
	// ...
	// NextKey_ver+1   -- (7)
	// NextKey_ver     -- (8)
	// NextKey_ver-1   -- (9)
	// ...
	// NextKey_0       -- (10)
	// ...
	// EOF
	for {
		mvccKey := MvccEncodeVersionKey(key, s.version)
		mvccK, v, err := s.store.Seek([]byte(mvccKey), s.version.Ver) // search for [3...EOF)
		if err != nil {
			if terror.ErrorEqual(err, engine.ErrNotFound) { // EOF
				return nil, nil, errors.Trace(kv.ErrNotExist)
			}
			return nil, nil, errors.Trace(err)
		}
		k, ver, err := MvccDecode(mvccK)
		if err != nil {
			return nil, nil, errors.Trace(err)
		}
		// quick test for exact mode
		if exact {
			if key.Cmp(k) != 0 || isTombstone(v) {
				return nil, nil, errors.Trace(kv.ErrNotExist)
			}
			return k, v, nil
		}
		if ver.Ver > s.version.Ver {
			// currently on [6...7]
			key = k // search for [8...EOF) next loop
			continue
		}
		// currently on [3...5] or [8...10]
		if isTombstone(v) {
			key = k.Next() // search for (5...EOF) or (10..EOF) next loop
			continue
		}
		// target found
		return k, v, nil
	}
}