Line data Source code
1 : // Copyright 2022 The LevelDB-Go and Pebble Authors. All rights reserved. Use 2 : // of this source code is governed by a BSD-style license that can be found in 3 : // the LICENSE file. 4 : 5 : package rangedel 6 : 7 : import ( 8 : "github.com/cockroachdb/pebble/internal/base" 9 : "github.com/cockroachdb/pebble/internal/invariants" 10 : "github.com/cockroachdb/pebble/internal/keyspan" 11 : ) 12 : 13 : // Encode takes a Span containing only range deletions. It invokes the provided 14 : // closure with the encoded internal keys that represent the Span's state. The 15 : // keys and values passed to emit are only valid until the closure returns. If 16 : // emit returns an error, Encode stops and returns the error. 17 1 : func Encode(s *keyspan.Span, emit func(k base.InternalKey, v []byte) error) error { 18 1 : for _, k := range s.Keys { 19 1 : if k.Kind() != base.InternalKeyKindRangeDelete { 20 0 : return base.CorruptionErrorf("pebble: rangedel.Encode cannot encode %s key", k.Kind()) 21 0 : } 22 1 : ik := base.InternalKey{ 23 1 : UserKey: s.Start, 24 1 : Trailer: k.Trailer, 25 1 : } 26 1 : if err := emit(ik, s.End); err != nil { 27 0 : return err 28 0 : } 29 : } 30 1 : return nil 31 : } 32 : 33 : // Decode takes an internal key pair encoding a range deletion and returns a 34 : // decoded keyspan containing the key. If keysDst is provided, the key will be 35 : // appended to keysDst, avoiding an allocation. 36 1 : func Decode(ik base.InternalKey, v []byte, keysDst []keyspan.Key) keyspan.Span { 37 1 : return keyspan.Span{ 38 1 : Start: ik.UserKey, 39 1 : End: v, 40 1 : Keys: append(keysDst, keyspan.Key{ 41 1 : Trailer: ik.Trailer, 42 1 : }), 43 1 : } 44 1 : } 45 : 46 : // DecodeIntoSpan decodes an internal key pair encoding a range deletion and 47 : // appends a key to the given span. The start and end keys must match those in 48 : // the span. 49 1 : func DecodeIntoSpan(cmp base.Compare, ik base.InternalKey, v []byte, s *keyspan.Span) error { 50 1 : // This function should only be called when ik.UserKey matches the Start of 51 1 : // the span we already have. If this is not the case, it is a bug in the 52 1 : // calling code. 53 1 : if invariants.Enabled && cmp(s.Start, ik.UserKey) != 0 { 54 0 : return base.AssertionFailedf("DecodeIntoSpan called with different start key") 55 0 : } 56 : // The value can come from disk or from the user, so we want to check the end 57 : // key in all builds. 58 1 : if cmp(s.End, v) != 0 { 59 0 : return base.CorruptionErrorf("pebble: corrupt range key fragmentation") 60 0 : } 61 1 : s.Keys = append(s.Keys, keyspan.Key{Trailer: ik.Trailer}) 62 1 : return nil 63 : }