0

Upgrade versions of vendored libs

This commit is contained in:
eleksir
2024-08-03 21:26:21 +03:00
parent 9bac4fb257
commit b6f8cf9155
812 changed files with 56387 additions and 31548 deletions

View File

@@ -132,6 +132,8 @@ type Writer struct {
separator Separator
successor Successor
tableFormat TableFormat
isStrictObsolete bool
writingToLowestLevel bool
cache *cache.Cache
restartInterval int
checksumType ChecksumType
@@ -166,6 +168,7 @@ type Writer struct {
props Properties
propCollectors []TablePropertyCollector
blockPropCollectors []BlockPropertyCollector
obsoleteCollector obsoleteKeyBlockPropertyCollector
blockPropsEncoder blockPropertiesEncoder
// filter accumulates the filter block. If populated, the filter ingests
// either the output of w.split (i.e. a prefix extractor) if w.split is not
@@ -215,6 +218,8 @@ type pointKeyInfo struct {
// prefixLen uses w.split, if not nil. Only computed when w.valueBlockWriter
// is not nil.
prefixLen int
// True iff the point was marked obsolete.
isObsolete bool
}
type coordinationState struct {
@@ -673,7 +678,12 @@ func (w *Writer) Set(key, value []byte) error {
if w.err != nil {
return w.err
}
return w.addPoint(base.MakeInternalKey(key, 0, InternalKeyKindSet), value)
if w.isStrictObsolete {
return errors.Errorf("use AddWithForceObsolete")
}
// forceObsolete is false based on the assumption that no RANGEDELs in the
// sstable delete the added points.
return w.addPoint(base.MakeInternalKey(key, 0, InternalKeyKindSet), value, false)
}
// Delete deletes the value for the given key. The sequence number is set to
@@ -685,7 +695,12 @@ func (w *Writer) Delete(key []byte) error {
if w.err != nil {
return w.err
}
return w.addPoint(base.MakeInternalKey(key, 0, InternalKeyKindDelete), nil)
if w.isStrictObsolete {
return errors.Errorf("use AddWithForceObsolete")
}
// forceObsolete is false based on the assumption that no RANGEDELs in the
// sstable delete the added points.
return w.addPoint(base.MakeInternalKey(key, 0, InternalKeyKindDelete), nil, false)
}
// DeleteRange deletes all of the keys (and values) in the range [start,end)
@@ -711,7 +726,13 @@ func (w *Writer) Merge(key, value []byte) error {
if w.err != nil {
return w.err
}
return w.addPoint(base.MakeInternalKey(key, 0, InternalKeyKindMerge), value)
if w.isStrictObsolete {
return errors.Errorf("use AddWithForceObsolete")
}
// forceObsolete is false based on the assumption that no RANGEDELs in the
// sstable that delete the added points. If the user configured this writer
// to be strict-obsolete, addPoint will reject the addition of this MERGE.
return w.addPoint(base.MakeInternalKey(key, 0, InternalKeyKindMerge), value, false)
}
// Add adds a key/value pair to the table being written. For a given Writer,
@@ -721,6 +742,24 @@ func (w *Writer) Merge(key, value []byte) error {
// point entries. Additionally, range deletion tombstones must be fragmented
// (i.e. by keyspan.Fragmenter).
func (w *Writer) Add(key InternalKey, value []byte) error {
if w.isStrictObsolete {
return errors.Errorf("use AddWithForceObsolete")
}
return w.AddWithForceObsolete(key, value, false)
}
// AddWithForceObsolete must be used when writing a strict-obsolete sstable.
//
// forceObsolete indicates whether the caller has determined that this key is
// obsolete even though it may be the latest point key for this userkey. This
// should be set to true for keys obsoleted by RANGEDELs, and is required for
// strict-obsolete sstables.
//
// Note that there are two properties, S1 and S2 (see comment in format.go)
// that strict-obsolete ssts must satisfy. S2, due to RANGEDELs, is solely the
// responsibility of the caller. S1 is solely the responsibility of the
// callee.
func (w *Writer) AddWithForceObsolete(key InternalKey, value []byte, forceObsolete bool) error {
if w.err != nil {
return w.err
}
@@ -735,7 +774,7 @@ func (w *Writer) Add(key InternalKey, value []byte) error {
"pebble: range keys must be added via one of the RangeKey* functions")
return w.err
}
return w.addPoint(key, value)
return w.addPoint(key, value, forceObsolete)
}
func (w *Writer) makeAddPointDecisionV2(key InternalKey) error {
@@ -745,12 +784,7 @@ func (w *Writer) makeAddPointDecisionV2(key InternalKey) error {
return nil
}
if !w.disableKeyOrderChecks {
prevPointUserKey := w.dataBlockBuf.dataBlock.curKey
n := len(prevPointUserKey) - base.InternalTrailerLen
if n < 0 {
panic("corrupt key in blockWriter buffer")
}
prevPointUserKey = prevPointUserKey[:n:n]
prevPointUserKey := w.dataBlockBuf.dataBlock.getCurUserKey()
cmpUser := w.compare(prevPointUserKey, key.UserKey)
if cmpUser > 0 || (cmpUser == 0 && prevTrailer <= key.Trailer) {
return errors.Errorf(
@@ -762,9 +796,17 @@ func (w *Writer) makeAddPointDecisionV2(key InternalKey) error {
return nil
}
// REQUIRES: at least one point has been written to the Writer.
func (w *Writer) getLastPointUserKey() []byte {
if w.dataBlockBuf.dataBlock.nEntries == 0 {
panic(errors.AssertionFailedf("no point keys added to writer"))
}
return w.dataBlockBuf.dataBlock.getCurUserKey()
}
func (w *Writer) makeAddPointDecisionV3(
key InternalKey, valueLen int,
) (setHasSamePrefix bool, writeToValueBlock bool, err error) {
) (setHasSamePrefix bool, writeToValueBlock bool, isObsolete bool, err error) {
prevPointKeyInfo := w.lastPointKeyInfo
w.lastPointKeyInfo.userKeyLen = len(key.UserKey)
w.lastPointKeyInfo.prefixLen = w.lastPointKeyInfo.userKeyLen
@@ -772,18 +814,16 @@ func (w *Writer) makeAddPointDecisionV3(
w.lastPointKeyInfo.prefixLen = w.split(key.UserKey)
}
w.lastPointKeyInfo.trailer = key.Trailer
if w.dataBlockBuf.dataBlock.nEntries == 0 {
return false, false, nil
w.lastPointKeyInfo.isObsolete = false
if !w.meta.HasPointKeys {
return false, false, false, nil
}
prevPointUserKey := w.dataBlockBuf.dataBlock.curKey
n := len(prevPointUserKey) - base.InternalTrailerLen
if n < 0 {
panic("corrupt key in blockWriter buffer")
}
prevPointUserKey = prevPointUserKey[:n:n]
keyKind := base.TrailerKind(key.Trailer)
prevPointUserKey := w.getLastPointUserKey()
prevPointKey := InternalKey{UserKey: prevPointUserKey, Trailer: prevPointKeyInfo.trailer}
considerWriteToValueBlock := base.TrailerKind(prevPointKeyInfo.trailer) == InternalKeyKindSet &&
base.TrailerKind(key.Trailer) == InternalKeyKindSet
prevKeyKind := base.TrailerKind(prevPointKeyInfo.trailer)
considerWriteToValueBlock := prevKeyKind == InternalKeyKindSet &&
keyKind == InternalKeyKindSet
if considerWriteToValueBlock && !w.requiredInPlaceValueBound.IsEmpty() {
keyPrefix := key.UserKey[:w.lastPointKeyInfo.prefixLen]
cmpUpper := w.compare(
@@ -812,14 +852,63 @@ func (w *Writer) makeAddPointDecisionV3(
} else {
cmpUser = w.compare(prevPointUserKey, key.UserKey)
}
// Ensure that no one adds a point key kind without considering the obsolete
// handling for that kind.
switch keyKind {
case InternalKeyKindSet, InternalKeyKindSetWithDelete, InternalKeyKindMerge,
InternalKeyKindDelete, InternalKeyKindSingleDelete, InternalKeyKindDeleteSized:
default:
panic(errors.AssertionFailedf("unexpected key kind %s", keyKind.String()))
}
// If same user key, then the current key is obsolete if any of the
// following is true:
// C1 The prev key was obsolete.
// C2 The prev key was not a MERGE. When the previous key is a MERGE we must
// preserve SET* and MERGE since their values will be merged into the
// previous key. We also must preserve DEL* since there may be an older
// SET*/MERGE in a lower level that must not be merged with the MERGE --
// if we omit the DEL* that lower SET*/MERGE will become visible.
//
// Regardless of whether it is the same user key or not
// C3 The current key is some kind of point delete, and we are writing to
// the lowest level, then it is also obsolete. The correctness of this
// relies on the same user key not spanning multiple sstables in a level.
//
// C1 ensures that for a user key there is at most one transition from
// !obsolete to obsolete. Consider a user key k, for which the first n keys
// are not obsolete. We consider the various value of n:
//
// n = 0: This happens due to forceObsolete being set by the caller, or due
// to C3. forceObsolete must only be set due a RANGEDEL, and that RANGEDEL
// must also delete all the lower seqnums for the same user key. C3 triggers
// due to a point delete and that deletes all the lower seqnums for the same
// user key.
//
// n = 1: This is the common case. It happens when the first key is not a
// MERGE, or the current key is some kind of point delete.
//
// n > 1: This is due to a sequence of MERGE keys, potentially followed by a
// single non-MERGE key.
isObsoleteC1AndC2 := cmpUser == 0 &&
(prevPointKeyInfo.isObsolete || prevKeyKind != InternalKeyKindMerge)
isObsoleteC3 := w.writingToLowestLevel &&
(keyKind == InternalKeyKindDelete || keyKind == InternalKeyKindSingleDelete ||
keyKind == InternalKeyKindDeleteSized)
isObsolete = isObsoleteC1AndC2 || isObsoleteC3
// TODO(sumeer): storing isObsolete SET and SETWITHDEL in value blocks is
// possible, but requires some care in documenting and checking invariants.
// There is code that assumes nothing in value blocks because of single MVCC
// version (those should be ok). We have to ensure setHasSamePrefix is
// correctly initialized here etc.
if !w.disableKeyOrderChecks &&
(cmpUser > 0 || (cmpUser == 0 && prevPointKeyInfo.trailer <= key.Trailer)) {
return false, false, errors.Errorf(
return false, false, false, errors.Errorf(
"pebble: keys must be added in strictly increasing order: %s, %s",
prevPointKey.Pretty(w.formatKey), key.Pretty(w.formatKey))
}
if !considerWriteToValueBlock {
return false, false, nil
return false, false, isObsolete, nil
}
// NB: it is possible that cmpUser == 0, i.e., these two SETs have identical
// user keys (because of an open snapshot). This should be the rare case.
@@ -832,19 +921,24 @@ func (w *Writer) makeAddPointDecisionV3(
if considerWriteToValueBlock && valueLen <= tinyValueThreshold {
considerWriteToValueBlock = false
}
return setHasSamePrefix, considerWriteToValueBlock, nil
return setHasSamePrefix, considerWriteToValueBlock, isObsolete, nil
}
func (w *Writer) addPoint(key InternalKey, value []byte) error {
func (w *Writer) addPoint(key InternalKey, value []byte, forceObsolete bool) error {
if w.isStrictObsolete && key.Kind() == InternalKeyKindMerge {
return errors.Errorf("MERGE not supported in a strict-obsolete sstable")
}
var err error
var setHasSameKeyPrefix, writeToValueBlock, addPrefixToValueStoredWithKey bool
var isObsolete bool
maxSharedKeyLen := len(key.UserKey)
if w.valueBlockWriter != nil {
// maxSharedKeyLen is limited to the prefix of the preceding key. If the
// preceding key was in a different block, then the blockWriter will
// ignore this maxSharedKeyLen.
maxSharedKeyLen = w.lastPointKeyInfo.prefixLen
setHasSameKeyPrefix, writeToValueBlock, err = w.makeAddPointDecisionV3(key, len(value))
setHasSameKeyPrefix, writeToValueBlock, isObsolete, err =
w.makeAddPointDecisionV3(key, len(value))
addPrefixToValueStoredWithKey = base.TrailerKind(key.Trailer) == InternalKeyKindSet
} else {
err = w.makeAddPointDecisionV2(key)
@@ -852,6 +946,8 @@ func (w *Writer) addPoint(key InternalKey, value []byte) error {
if err != nil {
return err
}
isObsolete = w.tableFormat >= TableFormatPebblev4 && (isObsolete || forceObsolete)
w.lastPointKeyInfo.isObsolete = isObsolete
var valueStoredWithKey []byte
var prefix valuePrefix
var valueStoredWithKeyLen int
@@ -907,16 +1003,19 @@ func (w *Writer) addPoint(key InternalKey, value []byte) error {
return err
}
}
if w.tableFormat >= TableFormatPebblev4 {
w.obsoleteCollector.AddPoint(isObsolete)
}
w.maybeAddToFilter(key.UserKey)
w.dataBlockBuf.dataBlock.addWithOptionalValuePrefix(
key, valueStoredWithKey, maxSharedKeyLen, addPrefixToValueStoredWithKey, prefix,
key, isObsolete, valueStoredWithKey, maxSharedKeyLen, addPrefixToValueStoredWithKey, prefix,
setHasSameKeyPrefix)
w.meta.updateSeqNum(key.SeqNum())
if !w.meta.HasPointKeys {
k := base.DecodeInternalKey(w.dataBlockBuf.dataBlock.curKey)
k := w.dataBlockBuf.dataBlock.getCurKey()
// NB: We need to ensure that SmallestPoint.UserKey is set, so we create
// an InternalKey which is semantically identical to the key, but won't
// have a nil UserKey. We do this, because key.UserKey could be nil, and
@@ -932,7 +1031,22 @@ func (w *Writer) addPoint(key InternalKey, value []byte) error {
switch key.Kind() {
case InternalKeyKindDelete, InternalKeyKindSingleDelete:
w.props.NumDeletions++
w.props.RawPointTombstoneKeySize += uint64(key.Size())
w.props.RawPointTombstoneKeySize += uint64(len(key.UserKey))
case InternalKeyKindDeleteSized:
var size uint64
if len(value) > 0 {
var n int
size, n = binary.Uvarint(value)
if n <= 0 {
w.err = errors.Newf("%s key's value (%x) does not parse as uvarint",
errors.Safe(key.Kind().String()), value)
return w.err
}
}
w.props.NumDeletions++
w.props.NumSizedDeletions++
w.props.RawPointTombstoneKeySize += uint64(len(key.UserKey))
w.props.RawPointTombstoneValueSize += size
case InternalKeyKindMerge:
w.props.NumMergeOperands++
}
@@ -953,7 +1067,7 @@ func (w *Writer) addTombstone(key InternalKey, value []byte) error {
if !w.disableKeyOrderChecks && !w.rangeDelV1Format && w.rangeDelBlock.nEntries > 0 {
// Check that tombstones are being added in fragmented order. If the two
// tombstones overlap, their start and end keys must be identical.
prevKey := base.DecodeInternalKey(w.rangeDelBlock.curKey)
prevKey := w.rangeDelBlock.getCurKey()
switch c := w.compare(prevKey.UserKey, key.UserKey); {
case c > 0:
w.err = errors.Errorf("pebble: keys must be added in order: %s, %s",
@@ -1149,7 +1263,7 @@ func (w *Writer) encodeRangeKeySpan(span keyspan.Span) {
func (w *Writer) addRangeKey(key InternalKey, value []byte) error {
if !w.disableKeyOrderChecks && w.rangeKeyBlock.nEntries > 0 {
prevStartKey := base.DecodeInternalKey(w.rangeKeyBlock.curKey)
prevStartKey := w.rangeKeyBlock.getCurKey()
prevEndKey, _, ok := rangekey.DecodeEndKey(prevStartKey.Kind(), w.rangeKeyBlock.curValue)
if !ok {
// We panic here as we should have previously decoded and validated this
@@ -1295,7 +1409,7 @@ func (w *Writer) flush(key InternalKey) error {
// dataBlockBuf is added back to a sync.Pool. In this particular case, the
// byte slice which supports "sep" will eventually be copied when "sep" is
// added to the index block.
prevKey := base.DecodeInternalKey(w.dataBlockBuf.dataBlock.curKey)
prevKey := w.dataBlockBuf.dataBlock.getCurKey()
sep := w.indexEntrySep(prevKey, key, w.dataBlockBuf)
// We determine that we should flush an index block from the Writer client
// goroutine, but we actually finish the index block from the writeQueue.
@@ -1585,7 +1699,7 @@ func (w *Writer) finishIndexBlock(indexBuf *indexBlockBuf, props []byte) error {
nEntries: indexBuf.block.nEntries, properties: props,
}
w.indexSepAlloc, part.sep = cloneKeyWithBuf(
base.DecodeInternalKey(indexBuf.block.curKey), w.indexSepAlloc,
indexBuf.block.getCurKey(), w.indexSepAlloc,
)
bk := indexBuf.finish()
if len(w.indexBlockAlloc) < len(bk) {
@@ -1729,12 +1843,20 @@ func (w *Writer) assertFormatCompatibility() error {
)
}
// PebbleDBv3: value blocks.
if (w.props.NumValueBlocks > 0 || w.props.NumValuesInValueBlocks > 0 ||
w.props.ValueBlocksSize > 0) && w.tableFormat < TableFormatPebblev3 {
return errors.Newf(
"table format version %s is less than the minimum required version %s for value blocks",
w.tableFormat, TableFormatPebblev3)
}
// PebbleDBv4: DELSIZED tombstones.
if w.props.NumSizedDeletions > 0 && w.tableFormat < TableFormatPebblev4 {
return errors.Newf(
"table format version %s is less than the minimum required version %s for sized deletion tombstones",
w.tableFormat, TableFormatPebblev4)
}
return nil
}
@@ -1781,7 +1903,7 @@ func (w *Writer) Close() (err error) {
// however, if a dataBlock is flushed, then we add a key to the new w.dataBlockBuf in the
// addPoint function after the flush occurs.
if w.dataBlockBuf.dataBlock.nEntries >= 1 {
w.meta.SetLargestPointKey(base.DecodeInternalKey(w.dataBlockBuf.dataBlock.curKey).Clone())
w.meta.SetLargestPointKey(w.dataBlockBuf.dataBlock.getCurKey().Clone())
}
// Finish the last data block, or force an empty data block if there
@@ -1795,7 +1917,7 @@ func (w *Writer) Close() (err error) {
if err != nil {
return err
}
prevKey := base.DecodeInternalKey(w.dataBlockBuf.dataBlock.curKey)
prevKey := w.dataBlockBuf.dataBlock.getCurKey()
if err := w.addIndexEntrySync(prevKey, InternalKey{}, bhp, w.dataBlockBuf.tmp[:]); err != nil {
return err
}
@@ -1874,7 +1996,7 @@ func (w *Writer) Close() (err error) {
var rangeKeyBH BlockHandle
if w.props.NumRangeKeys() > 0 {
key := base.DecodeInternalKey(w.rangeKeyBlock.curKey)
key := w.rangeKeyBlock.getCurKey()
kind := key.Kind()
endKey, _, ok := rangekey.DecodeEndKey(kind, w.rangeKeyBlock.curValue)
if !ok {
@@ -2063,7 +2185,7 @@ func (o PreviousPointKeyOpt) UnsafeKey() base.InternalKey {
if o.w.dataBlockBuf.dataBlock.nEntries >= 1 {
// o.w.dataBlockBuf.dataBlock.curKey is guaranteed to point to the last point key
// which was added to the Writer.
return base.DecodeInternalKey(o.w.dataBlockBuf.dataBlock.curKey)
return o.w.dataBlockBuf.dataBlock.getCurKey()
}
return base.InternalKey{}
}
@@ -2092,6 +2214,8 @@ func NewWriter(writable objstorage.Writable, o WriterOptions, extraOpts ...Write
separator: o.Comparer.Separator,
successor: o.Comparer.Successor,
tableFormat: o.TableFormat,
isStrictObsolete: o.IsStrictObsolete,
writingToLowestLevel: o.WritingToLowestLevel,
cache: o.Cache,
restartInterval: o.BlockRestartInterval,
checksumType: o.Checksum,
@@ -2158,14 +2282,14 @@ func NewWriter(writable objstorage.Writable, o WriterOptions, extraOpts ...Write
}
}
w.props.ColumnFamilyID = math.MaxInt32
w.props.ComparerName = o.Comparer.Name
w.props.CompressionName = o.Compression.String()
w.props.MergerName = o.MergerName
w.props.PropertyCollectorNames = "[]"
w.props.ExternalFormatVersion = rocksDBExternalFormatVersion
if len(o.TablePropertyCollectors) > 0 || len(o.BlockPropertyCollectors) > 0 {
if len(o.TablePropertyCollectors) > 0 || len(o.BlockPropertyCollectors) > 0 ||
w.tableFormat >= TableFormatPebblev4 {
var buf bytes.Buffer
buf.WriteString("[")
if len(o.TablePropertyCollectors) > 0 {
@@ -2178,16 +2302,22 @@ func NewWriter(writable objstorage.Writable, o WriterOptions, extraOpts ...Write
buf.WriteString(w.propCollectors[i].Name())
}
}
numBlockPropertyCollectors := len(o.BlockPropertyCollectors)
if w.tableFormat >= TableFormatPebblev4 {
numBlockPropertyCollectors++
}
// shortID is a uint8, so we cannot exceed that number of block
// property collectors.
if numBlockPropertyCollectors > math.MaxUint8 {
w.err = errors.New("pebble: too many block property collectors")
return w
}
if numBlockPropertyCollectors > 0 {
w.blockPropCollectors = make([]BlockPropertyCollector, numBlockPropertyCollectors)
}
if len(o.BlockPropertyCollectors) > 0 {
// shortID is a uint8, so we cannot exceed that number of block
// property collectors.
if len(o.BlockPropertyCollectors) > math.MaxUint8 {
w.err = errors.New("pebble: too many block property collectors")
return w
}
// The shortID assigned to a collector is the same as its index in
// this slice.
w.blockPropCollectors = make([]BlockPropertyCollector, len(o.BlockPropertyCollectors))
for i := range o.BlockPropertyCollectors {
w.blockPropCollectors[i] = o.BlockPropertyCollectors[i]()
if i > 0 || len(o.TablePropertyCollectors) > 0 {
@@ -2196,6 +2326,13 @@ func NewWriter(writable objstorage.Writable, o WriterOptions, extraOpts ...Write
buf.WriteString(w.blockPropCollectors[i].Name())
}
}
if w.tableFormat >= TableFormatPebblev4 {
if numBlockPropertyCollectors > 1 || len(o.TablePropertyCollectors) > 0 {
buf.WriteString(",")
}
w.blockPropCollectors[numBlockPropertyCollectors-1] = &w.obsoleteCollector
buf.WriteString(w.obsoleteCollector.Name())
}
buf.WriteString("]")
w.props.PropertyCollectorNames = buf.String()
}
@@ -2229,3 +2366,85 @@ func init() {
}
private.SSTableInternalProperties = internalGetProperties
}
type obsoleteKeyBlockPropertyCollector struct {
blockIsNonObsolete bool
indexIsNonObsolete bool
tableIsNonObsolete bool
}
func encodeNonObsolete(isNonObsolete bool, buf []byte) []byte {
if isNonObsolete {
return buf
}
return append(buf, 't')
}
func (o *obsoleteKeyBlockPropertyCollector) Name() string {
return "obsolete-key"
}
func (o *obsoleteKeyBlockPropertyCollector) Add(key InternalKey, value []byte) error {
// Ignore.
return nil
}
func (o *obsoleteKeyBlockPropertyCollector) AddPoint(isObsolete bool) {
o.blockIsNonObsolete = o.blockIsNonObsolete || !isObsolete
}
func (o *obsoleteKeyBlockPropertyCollector) FinishDataBlock(buf []byte) ([]byte, error) {
o.tableIsNonObsolete = o.tableIsNonObsolete || o.blockIsNonObsolete
return encodeNonObsolete(o.blockIsNonObsolete, buf), nil
}
func (o *obsoleteKeyBlockPropertyCollector) AddPrevDataBlockToIndexBlock() {
o.indexIsNonObsolete = o.indexIsNonObsolete || o.blockIsNonObsolete
o.blockIsNonObsolete = false
}
func (o *obsoleteKeyBlockPropertyCollector) FinishIndexBlock(buf []byte) ([]byte, error) {
indexIsNonObsolete := o.indexIsNonObsolete
o.indexIsNonObsolete = false
return encodeNonObsolete(indexIsNonObsolete, buf), nil
}
func (o *obsoleteKeyBlockPropertyCollector) FinishTable(buf []byte) ([]byte, error) {
return encodeNonObsolete(o.tableIsNonObsolete, buf), nil
}
func (o *obsoleteKeyBlockPropertyCollector) UpdateKeySuffixes(
oldProp []byte, oldSuffix, newSuffix []byte,
) error {
_, err := propToIsObsolete(oldProp)
if err != nil {
return err
}
// Suffix rewriting currently loses the obsolete bit.
o.blockIsNonObsolete = true
return nil
}
// NB: obsoleteKeyBlockPropertyFilter is stateless. This aspect of the filter
// is used in table_cache.go for in-place modification of a filters slice.
type obsoleteKeyBlockPropertyFilter struct{}
func (o obsoleteKeyBlockPropertyFilter) Name() string {
return "obsolete-key"
}
// Intersects returns true if the set represented by prop intersects with
// the set in the filter.
func (o obsoleteKeyBlockPropertyFilter) Intersects(prop []byte) (bool, error) {
return propToIsObsolete(prop)
}
func propToIsObsolete(prop []byte) (bool, error) {
if len(prop) == 0 {
return true, nil
}
if len(prop) > 1 || prop[0] != 't' {
return false, errors.Errorf("unexpected property %x", prop)
}
return false, nil
}