// 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 } }