Skip to content

Commit fdb9dae

Browse files
committed
plumb block level synthetic prefix support
This patch enables the db user to ingest a virtual sst with a synthetic prefix and for higher level readers to plumb the synthetic prefix to the block iterator which will conduct prefix synthesis. Note that the db user can still ingest a virtual sst with a prefix _replacement_ rule, by passing the virtual sst the original prefix and the replacement prefix. This tranformation is different that block level prefix synthesis as it replaces the original prefix with the new prefix.
1 parent 2251410 commit fdb9dae

File tree

9 files changed

+280
-81
lines changed

9 files changed

+280
-81
lines changed

ingest.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1130,6 +1130,9 @@ type ExternalFile struct {
11301130
// is accessed as if those keys all instead have prefix SyntheticPrefix.
11311131
//
11321132
// SyntheticPrefix must be a prefix of both SmallestUserKey and LargestUserKey.
1133+
//
1134+
// NB: If the SyntheticPrefix is non-empty and the ContentPrefix is empty,
1135+
// then the read path will conduct block level prefix synthesis.
11331136
ContentPrefix, SyntheticPrefix []byte
11341137

11351138
// SyntheticSuffix will replace the suffix of every key in the file during

internal/manifest/version.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -294,9 +294,14 @@ func (m *FileMetadata) SyntheticSeqNum() sstable.SyntheticSeqNum {
294294

295295
// IterTransforms returns an sstable.IterTransforms that has SyntheticSeqNum set as needed.
296296
func (m *FileMetadata) IterTransforms() sstable.IterTransforms {
297+
var syntheticPrefix []byte
298+
if m.PrefixReplacement != nil && !m.PrefixReplacement.UsePrefixReplacementIterator() {
299+
syntheticPrefix = m.PrefixReplacement.SyntheticPrefix
300+
}
297301
return sstable.IterTransforms{
298302
SyntheticSeqNum: m.SyntheticSeqNum(),
299303
SyntheticSuffix: m.SyntheticSuffix,
304+
SyntheticPrefix: syntheticPrefix,
300305
}
301306
}
302307

sstable/block_test.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -384,6 +384,7 @@ func (c *checker) check(
384384
c.t.Logf("expected %q, got %q", eKey.UserKey, gKey.UserKey)
385385
require.Equal(c.t, eKey, gKey)
386386
require.Equal(c.t, eVal, gVal)
387+
c.notValid = false
387388
} else {
388389
c.t.Logf("expected nil, got %q", gKey)
389390
require.Nil(c.t, gKey)

sstable/reader.go

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -184,6 +184,11 @@ func (ss SyntheticSuffix) IsSet() bool {
184184
// with range keys cannot be iterated over with a synthetic prefix.
185185
type SyntheticPrefix []byte
186186

187+
// IsSet returns true if the synthetic prefix is not enpty.
188+
func (sp SyntheticPrefix) IsSet() bool {
189+
return len(sp) > 0
190+
}
191+
187192
// rawTombstonesOpt is a Reader open option for specifying that range
188193
// tombstones returned by Reader.NewRangeDelIter() should not be
189194
// fragmented. Used by debug tools to get a raw view of the tombstones
@@ -431,6 +436,9 @@ func (r *Reader) NewRawRangeDelIter(transforms IterTransforms) (keyspan.Fragment
431436
if transforms.SyntheticSuffix.IsSet() {
432437
return nil, errors.AssertionFailedf("synthetic suffix not supported with range del iterator")
433438
}
439+
if transforms.SyntheticPrefix.IsSet() {
440+
return nil, errors.AssertionFailedf("synthetic prefix not supported with range del iterator")
441+
}
434442
h, err := r.readRangeDel(nil /* stats */, nil /* iterStats */)
435443
if err != nil {
436444
return nil, err
@@ -459,6 +467,9 @@ func (r *Reader) NewRawRangeKeyIter(transforms IterTransforms) (keyspan.Fragment
459467
if transforms.SyntheticSuffix.IsSet() {
460468
return nil, errors.AssertionFailedf("synthetic suffix not supported with range key iterator")
461469
}
470+
if transforms.SyntheticPrefix.IsSet() {
471+
return nil, errors.AssertionFailedf("synthetic prefix not supported with range key iterator")
472+
}
462473
h, err := r.readRangeKey(nil /* stats */, nil /* iterStats */)
463474
if err != nil {
464475
return nil, err

sstable/reader_common.go

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,12 @@ type PrefixReplacement struct {
8080
SyntheticPrefix []byte
8181
}
8282

83+
// UsePrefixReplacementIterator returns true if the prefix replacement iterator
84+
// wrapper should be used.
85+
func (p *PrefixReplacement) UsePrefixReplacementIterator() bool {
86+
return p != nil && len(p.ContentPrefix) > 0
87+
}
88+
8389
// Apply replaces the content prefix in the key with the synthetic prefix.
8490
func (p *PrefixReplacement) Apply(key []byte) []byte {
8591
return p.replace(key, p.ContentPrefix, p.SyntheticPrefix)

sstable/reader_iter_single_lvl.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -259,7 +259,7 @@ func (i *singleLevelIterator) maybeVerifyKey(
259259
key := iKey.UserKey
260260
v := i.vState
261261
var uc, lc int
262-
if p := v.prefixChange; p != nil {
262+
if p := v.prefixChange; p != nil && len(p.ContentPrefix) > 0 {
263263
if !bytes.HasPrefix(key, p.ContentPrefix) {
264264
panic(fmt.Sprintf("key %q does not have content prefix %q", key, v.prefixChange.ContentPrefix))
265265
}
@@ -273,7 +273,7 @@ func (i *singleLevelIterator) maybeVerifyKey(
273273
uc = i.cmp(key, v.upper.UserKey)
274274
}
275275
if lc < 0 || uc > 0 || (uc == 0 && v.upper.IsExclusiveSentinel()) {
276-
panic(fmt.Sprintf("key %q out of singleLeveliterator virtual bounds %s %s", key, v.lower, v.lower))
276+
panic(fmt.Sprintf("key %q out of singleLeveliterator virtual bounds %s %s", key, v.lower.UserKey, v.upper.UserKey))
277277
}
278278
}
279279
return iKey, val

0 commit comments

Comments
 (0)