Skip to content

Commit a54616a

Browse files
committed
db: extract determineRightTableBounds from exciseTable
1 parent f07254f commit a54616a

File tree

1 file changed

+80
-86
lines changed

1 file changed

+80
-86
lines changed

excise.go

Lines changed: 80 additions & 86 deletions
Original file line numberDiff line numberDiff line change
@@ -72,21 +72,16 @@ func (d *DB) exciseTable(
7272
return nil, nil
7373
}
7474

75-
var iters iterSet
76-
var itersLoaded bool
77-
defer iters.CloseAll()
78-
loadItersIfNecessary := func() error {
79-
if itersLoaded {
80-
return nil
81-
}
82-
var err error
83-
iters, err = d.newIters(ctx, m, &IterOptions{
84-
Category: categoryIngest,
85-
layer: manifest.Level(level),
86-
}, internalIterOpts{}, iterPointKeys|iterRangeDeletions|iterRangeKeys)
87-
itersLoaded = true
88-
return err
75+
// The file partially overlaps the excise span; we will need to open it to
76+
// determine tight bounds for the left-over table(s).
77+
iters, err := d.newIters(ctx, m, &IterOptions{
78+
Category: categoryIngest,
79+
layer: manifest.Level(level),
80+
}, internalIterOpts{}, iterPointKeys|iterRangeDeletions|iterRangeKeys)
81+
if err != nil {
82+
return nil, err
8983
}
84+
defer iters.CloseAll()
9085

9186
needsBacking := false
9287
// Create a file to the left of the excise span, if necessary.
@@ -123,9 +118,6 @@ func (d *DB) exciseTable(
123118
LargestSeqNumAbsolute: m.LargestSeqNumAbsolute,
124119
SyntheticPrefixAndSuffix: m.SyntheticPrefixAndSuffix,
125120
}
126-
if err := loadItersIfNecessary(); err != nil {
127-
return nil, err
128-
}
129121
if err := determineLeftTableBounds(d.cmp, m, leftFile, exciseSpan.Start, iters); err != nil {
130122
return nil, err
131123
}
@@ -179,70 +171,8 @@ func (d *DB) exciseTable(
179171
LargestSeqNumAbsolute: m.LargestSeqNumAbsolute,
180172
SyntheticPrefixAndSuffix: m.SyntheticPrefixAndSuffix,
181173
}
182-
if m.HasPointKeys && !exciseSpan.ContainsInternalKey(d.cmp, m.LargestPointKey) {
183-
// This file will probably contain point keys
184-
if err := loadItersIfNecessary(); err != nil {
185-
return nil, err
186-
}
187-
largestPointKey := m.LargestPointKey
188-
if kv := iters.Point().SeekGE(exciseSpan.End.Key, base.SeekGEFlagsNone); kv != nil {
189-
if exciseSpan.End.Kind == base.Inclusive && d.equal(exciseSpan.End.Key, kv.K.UserKey) {
190-
return nil, base.AssertionFailedf("cannot excise with an inclusive end key and data overlap at end key")
191-
}
192-
rightFile.ExtendPointKeyBounds(d.cmp, kv.K.Clone(), largestPointKey)
193-
}
194-
// Store the max of (exciseSpan.End, rdel.Start) in firstRangeDel. This
195-
// needs to be a copy if the key is owned by the range del iter.
196-
var firstRangeDel []byte
197-
rdel, err := iters.RangeDeletion().SeekGE(exciseSpan.End.Key)
198-
if err != nil {
199-
return nil, err
200-
} else if rdel != nil {
201-
firstRangeDel = append(firstRangeDel[:0], rdel.Start...)
202-
if d.cmp(firstRangeDel, exciseSpan.End.Key) < 0 {
203-
// NB: This can only be done if the end bound is exclusive.
204-
if exciseSpan.End.Kind != base.Exclusive {
205-
return nil, base.AssertionFailedf("cannot truncate rangedel during excise with an inclusive upper bound")
206-
}
207-
firstRangeDel = exciseSpan.End.Key
208-
}
209-
}
210-
if firstRangeDel != nil {
211-
smallestPointKey := rdel.SmallestKey()
212-
smallestPointKey.UserKey = firstRangeDel
213-
rightFile.ExtendPointKeyBounds(d.cmp, smallestPointKey, largestPointKey)
214-
}
215-
}
216-
if m.HasRangeKeys && !exciseSpan.ContainsInternalKey(d.cmp, m.LargestRangeKey) {
217-
// This file will probably contain range keys.
218-
if err := loadItersIfNecessary(); err != nil {
219-
return nil, err
220-
}
221-
largestRangeKey := m.LargestRangeKey
222-
// Store the max of (exciseSpan.End, rkey.Start) in firstRangeKey. This
223-
// needs to be a copy if the key is owned by the range key iter.
224-
var firstRangeKey []byte
225-
rkey, err := iters.RangeKey().SeekGE(exciseSpan.End.Key)
226-
if err != nil {
227-
return nil, err
228-
} else if rkey != nil {
229-
firstRangeKey = append(firstRangeKey[:0], rkey.Start...)
230-
if d.cmp(firstRangeKey, exciseSpan.End.Key) < 0 {
231-
if exciseSpan.End.Kind != base.Exclusive {
232-
return nil, base.AssertionFailedf("cannot truncate range key during excise with an inclusive upper bound")
233-
}
234-
firstRangeKey = exciseSpan.End.Key
235-
}
236-
}
237-
if firstRangeKey != nil {
238-
smallestRangeKey := rkey.SmallestKey()
239-
smallestRangeKey.UserKey = firstRangeKey
240-
// We call ExtendRangeKeyBounds so any internal boundType fields are
241-
// set correctly. Note that this is mildly wasteful as we'll be comparing
242-
// rightFile.{Smallest,Largest}RangeKey with themselves, which can be
243-
// avoided if we exported ExtendOverallKeyBounds or so.
244-
rightFile.ExtendRangeKeyBounds(d.cmp, smallestRangeKey, largestRangeKey)
245-
}
174+
if err := determineRightTableBounds(d.cmp, m, rightFile, exciseSpan.End, iters); err != nil {
175+
return nil, err
246176
}
247177
if rightFile.HasRangeKeys || rightFile.HasPointKeys {
248178
var err error
@@ -331,9 +261,8 @@ func determineLeftTableBounds(
331261
) error {
332262
if originalTable.HasPointKeys && cmp(originalTable.SmallestPointKey.UserKey, exciseSpanStart) < 0 {
333263
// This file will probably contain point keys.
334-
smallestPointKey := originalTable.SmallestPointKey
335264
if kv := iters.Point().SeekLT(exciseSpanStart, base.SeekLTFlagsNone); kv != nil {
336-
leftTable.ExtendPointKeyBounds(cmp, smallestPointKey, kv.K.Clone())
265+
leftTable.ExtendPointKeyBounds(cmp, originalTable.SmallestPointKey, kv.K.Clone())
337266
}
338267
rdel, err := iters.RangeDeletion().SeekLT(exciseSpanStart)
339268
if err != nil {
@@ -346,12 +275,12 @@ func determineLeftTableBounds(
346275
// The key is owned by the range del iter, so we need to copy it.
347276
lastRangeDel = slices.Clone(rdel.End)
348277
}
349-
leftTable.ExtendPointKeyBounds(cmp, smallestPointKey, base.MakeExclusiveSentinelKey(InternalKeyKindRangeDelete, lastRangeDel))
278+
leftTable.ExtendPointKeyBounds(cmp, originalTable.SmallestPointKey,
279+
base.MakeExclusiveSentinelKey(InternalKeyKindRangeDelete, lastRangeDel))
350280
}
351281
}
352282

353283
if originalTable.HasRangeKeys && cmp(originalTable.SmallestRangeKey.UserKey, exciseSpanStart) < 0 {
354-
smallestRangeKey := originalTable.SmallestRangeKey
355284
rkey, err := iters.RangeKey().SeekLT(exciseSpanStart)
356285
if err != nil {
357286
return err
@@ -364,7 +293,72 @@ func determineLeftTableBounds(
364293
lastRangeKey = slices.Clone(rkey.End)
365294
}
366295
lastRangeKeyKind := rkey.Keys[0].Kind()
367-
leftTable.ExtendRangeKeyBounds(cmp, smallestRangeKey, base.MakeExclusiveSentinelKey(lastRangeKeyKind, lastRangeKey))
296+
leftTable.ExtendRangeKeyBounds(cmp, originalTable.SmallestRangeKey,
297+
base.MakeExclusiveSentinelKey(lastRangeKeyKind, lastRangeKey))
298+
}
299+
}
300+
return nil
301+
}
302+
303+
// determineRightTableBounds calculates the bounds for the table that remains to
304+
// the right of the excise span after excising originalFile.
305+
//
306+
// Sets the smallest and largest keys, as well as HasPointKeys/HasRangeKeys in
307+
// the right.
308+
//
309+
// Note that the case where exciseSpanEnd is Inclusive is very restrictive; we
310+
// are only allowed to excise if the original table has no keys or ranges
311+
// overlapping exciseSpanEnd.Key.
312+
func determineRightTableBounds(
313+
cmp Compare,
314+
originalTable, rightTable *tableMetadata,
315+
exciseSpanEnd base.UserKeyBoundary,
316+
iters iterSet,
317+
) error {
318+
if originalTable.HasPointKeys && !exciseSpanEnd.IsUpperBoundForInternalKey(cmp, originalTable.LargestPointKey) {
319+
if kv := iters.Point().SeekGE(exciseSpanEnd.Key, base.SeekGEFlagsNone); kv != nil {
320+
if exciseSpanEnd.Kind == base.Inclusive && cmp(exciseSpanEnd.Key, kv.K.UserKey) == 0 {
321+
return base.AssertionFailedf("cannot excise with an inclusive end key and data overlap at end key")
322+
}
323+
rightTable.ExtendPointKeyBounds(cmp, kv.K.Clone(), originalTable.LargestPointKey)
324+
}
325+
rdel, err := iters.RangeDeletion().SeekGE(exciseSpanEnd.Key)
326+
if err != nil {
327+
return err
328+
}
329+
if rdel != nil {
330+
// Use the larger of exciseSpanEnd.Key and rdel.Start.
331+
firstRangeDel := exciseSpanEnd.Key
332+
if cmp(rdel.Start, exciseSpanEnd.Key) > 0 {
333+
// The key is owned by the range del iter, so we need to copy it.
334+
firstRangeDel = slices.Clone(rdel.Start)
335+
} else if exciseSpanEnd.Kind != base.Exclusive {
336+
return base.AssertionFailedf("cannot truncate rangedel during excise with an inclusive upper bound")
337+
}
338+
rightTable.ExtendPointKeyBounds(cmp, base.InternalKey{
339+
UserKey: firstRangeDel,
340+
Trailer: rdel.SmallestKey().Trailer,
341+
}, originalTable.LargestPointKey)
342+
}
343+
}
344+
if originalTable.HasRangeKeys && !exciseSpanEnd.IsUpperBoundForInternalKey(cmp, originalTable.LargestRangeKey) {
345+
rkey, err := iters.RangeKey().SeekGE(exciseSpanEnd.Key)
346+
if err != nil {
347+
return err
348+
}
349+
if rkey != nil {
350+
// Use the larger of exciseSpanEnd.Key and rkey.Start.
351+
firstRangeKey := exciseSpanEnd.Key
352+
if cmp(rkey.Start, exciseSpanEnd.Key) > 0 {
353+
// The key is owned by the range key iter, so we need to copy it.
354+
firstRangeKey = slices.Clone(rkey.Start)
355+
} else if exciseSpanEnd.Kind != base.Exclusive {
356+
return base.AssertionFailedf("cannot truncate range key during excise with an inclusive upper bound")
357+
}
358+
rightTable.ExtendRangeKeyBounds(cmp, base.InternalKey{
359+
UserKey: firstRangeKey,
360+
Trailer: rkey.SmallestKey().Trailer,
361+
}, originalTable.LargestRangeKey)
368362
}
369363
}
370364
return nil

0 commit comments

Comments
 (0)