Skip to content

Commit e517734

Browse files
committed
internal/testkeys: move Slice, EveryN out of the interface
Move the Slice and EveryN funcs out of the Keyspace interface and into top-level funcs that accept a Keyspace.
1 parent 252e253 commit e517734

File tree

7 files changed

+81
-35
lines changed

7 files changed

+81
-35
lines changed

error_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -487,7 +487,7 @@ func TestDBCompactionCrash(t *testing.T) {
487487
const valLength = 4 << 10
488488
timestamps := []int{10, 5}
489489
ks := testkeys.Alpha(maxKeyLength)
490-
ks = ks.EveryN(10)
490+
ks = testkeys.EveryN(ks, 10)
491491
buf := make([]byte, ks.MaxLen()+testkeys.MaxSuffixLen)
492492
vbuf := make([]byte, valLength)
493493
b := d.NewBatch()

internal/testkeys/testkeys.go

Lines changed: 69 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -189,14 +189,6 @@ type Keyspace interface {
189189
// keyspace. This is only guaranteed to return an upper bound.
190190
MaxLen() int
191191

192-
// Slice returns the sub-keyspace from index i, inclusive, to index j,
193-
// exclusive. The receiver is unmodified.
194-
Slice(i, j uint64) Keyspace
195-
196-
// EveryN returns a key space that includes 1 key for every N keys in the
197-
// original keyspace. The receiver is unmodified.
198-
EveryN(n uint64) Keyspace
199-
200192
// key writes the i-th key to the buffer and returns the length.
201193
key(buf []byte, i uint64) int
202194
}
@@ -205,8 +197,8 @@ type Keyspace interface {
205197
// disjoint keys evenly distributed across the keyspace.
206198
func Divvy(ks Keyspace, n uint64) []Keyspace {
207199
ret := make([]Keyspace, n)
208-
for i := uint64(0); i < n; i++ {
209-
ret[i] = ks.Slice(i, ks.Count()).EveryN(n)
200+
for i := range n {
201+
ret[i] = EveryN(Slice(ks, i, ks.Count()), n)
210202
}
211203
return ret
212204
}
@@ -312,19 +304,6 @@ func (a alphabet) MaxLen() int {
312304
return a.maxLength
313305
}
314306

315-
func (a alphabet) Slice(i, j uint64) Keyspace {
316-
s := a
317-
s.headSkip += i
318-
s.tailSkip += a.Count() - j
319-
return s
320-
}
321-
322-
func (a alphabet) EveryN(n uint64) Keyspace {
323-
s := a
324-
s.increment *= n
325-
return s
326-
}
327-
328307
func keyCount(n, l int) uint64 {
329308
// The number of representable keys in the keyspace is a function of the
330309
// length of the alphabet n and the max key length l:
@@ -491,3 +470,70 @@ func assertLE(a, b []byte) {
491470
panic(fmt.Sprintf("invalid key ordering: %q > %q", a, b))
492471
}
493472
}
473+
474+
// Slice returns the sub-keyspace from index i, inclusive, to index j,
475+
// exclusive. The receiver is unmodified.
476+
func Slice(ks Keyspace, i, j uint64) Keyspace {
477+
if i >= ks.Count() || j > ks.Count() {
478+
panic(errors.AssertionFailedf("invalid slice: [%d,%d) of keyspace with %d keys", i, j, ks.Count()))
479+
}
480+
return &sliceKeyspace{ks: ks, i: i, j: j}
481+
}
482+
483+
type sliceKeyspace struct {
484+
ks Keyspace
485+
i, j uint64
486+
}
487+
488+
// Count returns the number of keys that exist within this keyspace.
489+
func (s *sliceKeyspace) Count() uint64 {
490+
return s.j - s.i
491+
}
492+
493+
// MaxLen returns the maximum length, in bytes, of a key within this
494+
// keyspace. This is only guaranteed to return an upper bound.
495+
func (s *sliceKeyspace) MaxLen() int {
496+
return s.ks.MaxLen()
497+
}
498+
499+
// key writes the i-th key to the buffer and returns the length.
500+
func (s *sliceKeyspace) key(buf []byte, i uint64) int {
501+
return s.ks.key(buf, s.i+i)
502+
}
503+
504+
// EveryN returns the keyspace consisting of every n-th key in the provided
505+
// keyspace.
506+
func EveryN(ks Keyspace, n uint64) Keyspace {
507+
innerCount := ks.Count()
508+
c := innerCount / n
509+
// We are returning keys at index 0, n, 2n, ... up to cn (to be determined
510+
// whether inclusive or exclusive), such that the last key is < innerCount.
511+
// Since cn < innerCount, it becomes inclusive and we return c+1 keys (hence
512+
// this increment).
513+
if innerCount%n > 0 {
514+
c++
515+
}
516+
return &everyNKeyspace{ks: ks, n: n, c: c}
517+
}
518+
519+
type everyNKeyspace struct {
520+
ks Keyspace
521+
n uint64
522+
c uint64
523+
}
524+
525+
// Count returns the number of keys that exist within this keyspace.
526+
func (e everyNKeyspace) Count() uint64 {
527+
return e.c
528+
}
529+
530+
// MaxLen returns the maximum length, in bytes, of a key within this
531+
// keyspace. This is only guaranteed to return an upper bound.
532+
func (e everyNKeyspace) MaxLen() int {
533+
return e.ks.MaxLen()
534+
}
535+
536+
// key writes the i-th key to the buffer and returns the length.
537+
func (e everyNKeyspace) key(buf []byte, i uint64) int {
538+
return e.ks.key(buf, i*e.n)
539+
}

internal/testkeys/testkeys_test.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -122,11 +122,11 @@ func TestSlice(t *testing.T) {
122122
want string
123123
}{
124124
{Alpha(1), 1, 25, "b c d e f g h i j k l m n o p q r s t u v w x y"},
125-
{Alpha(1).Slice(1, 25), 1, 23, "c d e f g h i j k l m n o p q r s t u v w x"},
126-
{Alpha(1).Slice(1, 25).Slice(1, 23), 10, 22, "m n o p q r s t u v w x"},
125+
{Slice(Alpha(1), 1, 25), 1, 23, "c d e f g h i j k l m n o p q r s t u v w x"},
126+
{Slice(Slice(Alpha(1), 1, 25), 1, 23), 10, 22, "m n o p q r s t u v w x"},
127127
}
128128
for _, tc := range testCases {
129-
got := keyspaceToString(tc.orig.Slice(tc.i, tc.j))
129+
got := keyspaceToString(Slice(tc.orig, tc.i, tc.j))
130130
if got != tc.want {
131131
t.Errorf("(%q).Slice(%d, %d) = %q, want %q",
132132
keyspaceToString(tc.orig), tc.i, tc.j, got, tc.want)

iterator_test.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2469,7 +2469,7 @@ func BenchmarkIteratorScan(b *testing.B) {
24692469
// characters of lengths up to `maxPrefixLen` and reduce it down
24702470
// to `keyCount` keys by picking every 1 key every `keyCount` keys.
24712471
keys := testkeys.Alpha(maxPrefixLen)
2472-
keys = keys.EveryN(keys.Count() / keyCount)
2472+
keys = testkeys.EveryN(keys, keys.Count()/keyCount)
24732473
if keys.Count() < keyCount {
24742474
b.Fatalf("expected %d keys, found %d", keyCount, keys.Count())
24752475
}
@@ -2532,10 +2532,10 @@ func BenchmarkIteratorScanNextPrefix(b *testing.B) {
25322532
for l := readAmp; l > 0; l-- {
25332533
ks := testkeys.Alpha(l)
25342534
if step := ks.Count() / uint64(maxKeysPerLevel); step > 1 {
2535-
ks = ks.EveryN(step)
2535+
ks = testkeys.EveryN(ks, step)
25362536
}
25372537
if ks.Count() > uint64(maxKeysPerLevel) {
2538-
ks = ks.Slice(0, uint64(maxKeysPerLevel))
2538+
ks = testkeys.Slice(ks, 0, uint64(maxKeysPerLevel))
25392539
}
25402540

25412541
batch := d.NewBatch()

sstable/random_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -365,7 +365,7 @@ func buildRandomSSTable(f vfs.File, cfg randomTableConfig) (*WriterMetadata, err
365365
// Constrain the space we generate keys to the middle 90% of the keyspace.
366366
// This helps exercise code paths that are only run when a seek key is
367367
// beyond or before all index block entries.
368-
sstKeys := cfg.keys.Slice(cfg.keys.Count()/20, cfg.keys.Count()-cfg.keys.Count()/20)
368+
sstKeys := testkeys.Slice(cfg.keys, cfg.keys.Count()/20, cfg.keys.Count()-cfg.keys.Count()/20)
369369
randomKey := func() keyID {
370370
k := keyID{
371371
idx: cfg.rng.Uint64N(sstKeys.Count()),

sstable/reader_test.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2177,7 +2177,7 @@ func BenchmarkIteratorScanManyVersions(b *testing.B) {
21772177
// lengths up to unsharedPrefixLen and reduce it down to keyCount keys by
21782178
// picking every 1 key every keyCount keys.
21792179
keys := testkeys.Alpha(unsharedPrefixLen)
2180-
keys = keys.EveryN(keys.Count() / keyCount)
2180+
keys = testkeys.EveryN(keys, keys.Count()/keyCount)
21812181
if keys.Count() < keyCount {
21822182
b.Fatalf("expected %d keys, found %d", keyCount, keys.Count())
21832183
}
@@ -2297,7 +2297,7 @@ func BenchmarkIteratorScanNextPrefix(b *testing.B) {
22972297
// lengths up to unsharedPrefixLen and reduce it down to keyCount keys by
22982298
// picking every 1 key every keyCount keys.
22992299
keys := testkeys.Alpha(unsharedPrefixLen)
2300-
keys = keys.EveryN(keys.Count() / keyCount)
2300+
keys = testkeys.EveryN(keys, keys.Count()/keyCount)
23012301
if keys.Count() < keyCount {
23022302
b.Fatalf("expected %d keys, found %d", keyCount, keys.Count())
23032303
}
@@ -2464,7 +2464,7 @@ func BenchmarkIteratorScanObsolete(b *testing.B) {
24642464
// lengths up to unsharedPrefixLen and reduce it down to keyCount keys by
24652465
// picking every 1 key every keyCount keys.
24662466
keys := testkeys.Alpha(keyLen)
2467-
keys = keys.EveryN(keys.Count() / keyCount)
2467+
keys = testkeys.EveryN(keys, keys.Count()/keyCount)
24682468
if keys.Count() < keyCount {
24692469
b.Fatalf("expected %d keys, found %d", keyCount, keys.Count())
24702470
}

sstable/writer_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1076,7 +1076,7 @@ func TestWriter_TableFormatCompatibility(t *testing.T) {
10761076
func TestWriterRace(t *testing.T) {
10771077
defer leaktest.AfterTest(t)()
10781078
ks := testkeys.Alpha(5)
1079-
ks = ks.EveryN(ks.Count() / 1_000)
1079+
ks = testkeys.EveryN(ks, ks.Count()/1_000)
10801080
keys := make([][]byte, ks.Count())
10811081
for ki := 0; ki < len(keys); ki++ {
10821082
keys[ki] = testkeys.Key(ks, uint64(ki))

0 commit comments

Comments
 (0)