github.com/zuoyebang/bitalostable@v1.0.1-0.20240229032404-e3b99a834294/iterator_test.go (about)

     1  // Copyright 2013 The LevelDB-Go and Pebble and Bitalostored 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 bitalostable
     6  
     7  import (
     8  	"bytes"
     9  	"flag"
    10  	"fmt"
    11  	"io"
    12  	"runtime"
    13  	"sort"
    14  	"strconv"
    15  	"strings"
    16  	"sync/atomic"
    17  	"testing"
    18  	"time"
    19  
    20  	"github.com/cockroachdb/errors"
    21  	"github.com/stretchr/testify/require"
    22  	"github.com/zuoyebang/bitalostable/internal/base"
    23  	"github.com/zuoyebang/bitalostable/internal/datadriven"
    24  	"github.com/zuoyebang/bitalostable/internal/keyspan"
    25  	"github.com/zuoyebang/bitalostable/internal/manifest"
    26  	"github.com/zuoyebang/bitalostable/internal/testkeys"
    27  	"github.com/zuoyebang/bitalostable/internal/testkeys/blockprop"
    28  	"github.com/zuoyebang/bitalostable/sstable"
    29  	"github.com/zuoyebang/bitalostable/vfs"
    30  	"golang.org/x/exp/rand"
    31  )
    32  
    33  var testKeyValuePairs = []string{
    34  	"10:10",
    35  	"11:11",
    36  	"12:12",
    37  	"13:13",
    38  	"14:14",
    39  	"15:15",
    40  	"16:16",
    41  	"17:17",
    42  	"18:18",
    43  	"19:19",
    44  }
    45  
    46  type fakeIter struct {
    47  	lower    []byte
    48  	upper    []byte
    49  	keys     []InternalKey
    50  	vals     [][]byte
    51  	index    int
    52  	valid    bool
    53  	closeErr error
    54  }
    55  
    56  // fakeIter implements the base.InternalIterator interface.
    57  var _ base.InternalIterator = (*fakeIter)(nil)
    58  
    59  func fakeIkey(s string) InternalKey {
    60  	j := strings.Index(s, ":")
    61  	seqNum, err := strconv.Atoi(s[j+1:])
    62  	if err != nil {
    63  		panic(err)
    64  	}
    65  	return base.MakeInternalKey([]byte(s[:j]), uint64(seqNum), InternalKeyKindSet)
    66  }
    67  
    68  func newFakeIterator(closeErr error, keys ...string) *fakeIter {
    69  	ikeys := make([]InternalKey, len(keys))
    70  	for i, k := range keys {
    71  		ikeys[i] = fakeIkey(k)
    72  	}
    73  	return &fakeIter{
    74  		keys:     ikeys,
    75  		index:    0,
    76  		valid:    len(ikeys) > 0,
    77  		closeErr: closeErr,
    78  	}
    79  }
    80  
    81  func (f *fakeIter) String() string {
    82  	return "fake"
    83  }
    84  
    85  func (f *fakeIter) SeekGE(key []byte, flags base.SeekGEFlags) (*InternalKey, []byte) {
    86  	f.valid = false
    87  	for f.index = 0; f.index < len(f.keys); f.index++ {
    88  		if DefaultComparer.Compare(key, f.key().UserKey) <= 0 {
    89  			if f.upper != nil && DefaultComparer.Compare(f.upper, f.key().UserKey) <= 0 {
    90  				return nil, nil
    91  			}
    92  			f.valid = true
    93  			return f.Key(), f.Value()
    94  		}
    95  	}
    96  	return nil, nil
    97  }
    98  
    99  func (f *fakeIter) SeekPrefixGE(
   100  	prefix, key []byte, flags base.SeekGEFlags,
   101  ) (*base.InternalKey, []byte) {
   102  	return f.SeekGE(key, flags)
   103  }
   104  
   105  func (f *fakeIter) SeekLT(key []byte, flags base.SeekLTFlags) (*InternalKey, []byte) {
   106  	f.valid = false
   107  	for f.index = len(f.keys) - 1; f.index >= 0; f.index-- {
   108  		if DefaultComparer.Compare(key, f.key().UserKey) > 0 {
   109  			if f.lower != nil && DefaultComparer.Compare(f.lower, f.key().UserKey) > 0 {
   110  				return nil, nil
   111  			}
   112  			f.valid = true
   113  			return f.Key(), f.Value()
   114  		}
   115  	}
   116  	return nil, nil
   117  }
   118  
   119  func (f *fakeIter) First() (*InternalKey, []byte) {
   120  	f.valid = false
   121  	f.index = -1
   122  	if key, _ := f.Next(); key == nil {
   123  		return nil, nil
   124  	}
   125  	if f.upper != nil && DefaultComparer.Compare(f.upper, f.key().UserKey) <= 0 {
   126  		return nil, nil
   127  	}
   128  	f.valid = true
   129  	return f.Key(), f.Value()
   130  }
   131  
   132  func (f *fakeIter) Last() (*InternalKey, []byte) {
   133  	f.valid = false
   134  	f.index = len(f.keys)
   135  	if key, _ := f.Prev(); key == nil {
   136  		return nil, nil
   137  	}
   138  	if f.lower != nil && DefaultComparer.Compare(f.lower, f.key().UserKey) > 0 {
   139  		return nil, nil
   140  	}
   141  	f.valid = true
   142  	return f.Key(), f.Value()
   143  }
   144  
   145  func (f *fakeIter) Next() (*InternalKey, []byte) {
   146  	f.valid = false
   147  	if f.index == len(f.keys) {
   148  		return nil, nil
   149  	}
   150  	f.index++
   151  	if f.index == len(f.keys) {
   152  		return nil, nil
   153  	}
   154  	if f.upper != nil && DefaultComparer.Compare(f.upper, f.key().UserKey) <= 0 {
   155  		return nil, nil
   156  	}
   157  	f.valid = true
   158  	return f.Key(), f.Value()
   159  }
   160  
   161  func (f *fakeIter) Prev() (*InternalKey, []byte) {
   162  	f.valid = false
   163  	if f.index < 0 {
   164  		return nil, nil
   165  	}
   166  	f.index--
   167  	if f.index < 0 {
   168  		return nil, nil
   169  	}
   170  	if f.lower != nil && DefaultComparer.Compare(f.lower, f.key().UserKey) > 0 {
   171  		return nil, nil
   172  	}
   173  	f.valid = true
   174  	return f.Key(), f.Value()
   175  }
   176  
   177  // key returns the current Key the iterator is positioned at regardless of the
   178  // value of f.valid.
   179  func (f *fakeIter) key() *InternalKey {
   180  	return &f.keys[f.index]
   181  }
   182  
   183  func (f *fakeIter) Key() *InternalKey {
   184  	if f.valid {
   185  		return &f.keys[f.index]
   186  	}
   187  	// It is invalid to call Key() when Valid() returns false. Rather than
   188  	// returning nil here which would technically be more correct, return a
   189  	// non-nil key which is the behavior of some InternalIterator
   190  	// implementations. This provides better testing of users of
   191  	// InternalIterators.
   192  	if f.index < 0 {
   193  		return &f.keys[0]
   194  	}
   195  	return &f.keys[len(f.keys)-1]
   196  }
   197  
   198  func (f *fakeIter) Value() []byte {
   199  	if f.index >= 0 && f.index < len(f.vals) {
   200  		return f.vals[f.index]
   201  	}
   202  	return nil
   203  }
   204  
   205  func (f *fakeIter) Valid() bool {
   206  	return f.index >= 0 && f.index < len(f.keys) && f.valid
   207  }
   208  
   209  func (f *fakeIter) Error() error {
   210  	return f.closeErr
   211  }
   212  
   213  func (f *fakeIter) Close() error {
   214  	return f.closeErr
   215  }
   216  
   217  func (f *fakeIter) SetBounds(lower, upper []byte) {
   218  	f.lower = lower
   219  	f.upper = upper
   220  }
   221  
   222  // invalidatingIter tests unsafe key/value slice reuse by modifying the last
   223  // returned key/value to all 1s.
   224  type invalidatingIter struct {
   225  	iter        internalIterator
   226  	lastKey     *InternalKey
   227  	lastValue   []byte
   228  	ignoreKinds [base.InternalKeyKindMax + 1]bool
   229  }
   230  
   231  func newInvalidatingIter(iter internalIterator) *invalidatingIter {
   232  	return &invalidatingIter{iter: iter}
   233  }
   234  
   235  func (i *invalidatingIter) ignoreKind(kind base.InternalKeyKind) {
   236  	i.ignoreKinds[kind] = true
   237  }
   238  
   239  func (i *invalidatingIter) update(key *InternalKey, value []byte) (*InternalKey, []byte) {
   240  	i.zeroLast()
   241  
   242  	if key == nil {
   243  		i.lastKey = nil
   244  		i.lastValue = nil
   245  		return nil, nil
   246  	}
   247  
   248  	i.lastKey = &InternalKey{}
   249  	*i.lastKey = key.Clone()
   250  	i.lastValue = make([]byte, len(value))
   251  	copy(i.lastValue, value)
   252  	return i.lastKey, i.lastValue
   253  }
   254  
   255  func (i *invalidatingIter) zeroLast() {
   256  	if i.lastKey == nil {
   257  		return
   258  	}
   259  	if i.ignoreKinds[i.lastKey.Kind()] {
   260  		return
   261  	}
   262  
   263  	if i.lastKey != nil {
   264  		for j := range i.lastKey.UserKey {
   265  			i.lastKey.UserKey[j] = 0xff
   266  		}
   267  		i.lastKey.Trailer = 0
   268  	}
   269  	for j := range i.lastValue {
   270  		i.lastValue[j] = 0xff
   271  	}
   272  }
   273  
   274  func (i *invalidatingIter) SeekGE(key []byte, flags base.SeekGEFlags) (*InternalKey, []byte) {
   275  	return i.update(i.iter.SeekGE(key, flags))
   276  }
   277  
   278  func (i *invalidatingIter) SeekPrefixGE(
   279  	prefix, key []byte, flags base.SeekGEFlags,
   280  ) (*base.InternalKey, []byte) {
   281  	return i.update(i.iter.SeekPrefixGE(prefix, key, flags))
   282  }
   283  
   284  func (i *invalidatingIter) SeekLT(key []byte, flags base.SeekLTFlags) (*InternalKey, []byte) {
   285  	return i.update(i.iter.SeekLT(key, flags))
   286  }
   287  
   288  func (i *invalidatingIter) First() (*InternalKey, []byte) {
   289  	return i.update(i.iter.First())
   290  }
   291  
   292  func (i *invalidatingIter) Last() (*InternalKey, []byte) {
   293  	return i.update(i.iter.Last())
   294  }
   295  
   296  func (i *invalidatingIter) Next() (*InternalKey, []byte) {
   297  	return i.update(i.iter.Next())
   298  }
   299  
   300  func (i *invalidatingIter) Prev() (*InternalKey, []byte) {
   301  	return i.update(i.iter.Prev())
   302  }
   303  
   304  func (i *invalidatingIter) Error() error {
   305  	return i.iter.Error()
   306  }
   307  
   308  func (i *invalidatingIter) Close() error {
   309  	return i.iter.Close()
   310  }
   311  
   312  func (i *invalidatingIter) SetBounds(lower, upper []byte) {
   313  	i.iter.SetBounds(lower, upper)
   314  }
   315  
   316  func (i *invalidatingIter) String() string {
   317  	return i.iter.String()
   318  }
   319  
   320  // testIterator tests creating a combined iterator from a number of sub-
   321  // iterators. newFunc is a constructor function. splitFunc returns a random
   322  // split of the testKeyValuePairs slice such that walking a combined iterator
   323  // over those splits should recover the original key/value pairs in order.
   324  func testIterator(
   325  	t *testing.T,
   326  	newFunc func(...internalIterator) internalIterator,
   327  	splitFunc func(r *rand.Rand) [][]string,
   328  ) {
   329  	// Test pre-determined sub-iterators. The sub-iterators are designed
   330  	// so that the combined key/value pair order is the same whether the
   331  	// combined iterator is concatenating or merging.
   332  	testCases := []struct {
   333  		desc  string
   334  		iters []internalIterator
   335  		want  string
   336  	}{
   337  		{
   338  			"one sub-iterator",
   339  			[]internalIterator{
   340  				newFakeIterator(nil, "e:1", "w:2"),
   341  			},
   342  			"<e:1><w:2>.",
   343  		},
   344  		{
   345  			"two sub-iterators",
   346  			[]internalIterator{
   347  				newFakeIterator(nil, "a0:0"),
   348  				newFakeIterator(nil, "b1:1", "b2:2"),
   349  			},
   350  			"<a0:0><b1:1><b2:2>.",
   351  		},
   352  		{
   353  			"empty sub-iterators",
   354  			[]internalIterator{
   355  				newFakeIterator(nil),
   356  				newFakeIterator(nil),
   357  				newFakeIterator(nil),
   358  			},
   359  			".",
   360  		},
   361  		{
   362  			"sub-iterator errors",
   363  			[]internalIterator{
   364  				newFakeIterator(nil, "a0:0", "a1:1"),
   365  				newFakeIterator(errors.New("the sky is falling"), "b2:2", "b3:3", "b4:4"),
   366  				newFakeIterator(errors.New("run for your lives"), "c5:5", "c6:6"),
   367  			},
   368  			"<a0:0><a1:1><b2:2><b3:3><b4:4>err=the sky is falling",
   369  		},
   370  	}
   371  	for _, tc := range testCases {
   372  		var b bytes.Buffer
   373  		iter := newInvalidatingIter(newFunc(tc.iters...))
   374  		for key, _ := iter.First(); key != nil; key, _ = iter.Next() {
   375  			fmt.Fprintf(&b, "<%s:%d>", key.UserKey, key.SeqNum())
   376  		}
   377  		if err := iter.Close(); err != nil {
   378  			fmt.Fprintf(&b, "err=%v", err)
   379  		} else {
   380  			b.WriteByte('.')
   381  		}
   382  		if got := b.String(); got != tc.want {
   383  			t.Errorf("%s:\ngot  %q\nwant %q", tc.desc, got, tc.want)
   384  		}
   385  	}
   386  
   387  	// Test randomly generated sub-iterators.
   388  	r := rand.New(rand.NewSource(0))
   389  	for i, nBad := 0, 0; i < 1000; i++ {
   390  		bad := false
   391  
   392  		splits := splitFunc(r)
   393  		iters := make([]internalIterator, len(splits))
   394  		for i, split := range splits {
   395  			iters[i] = newFakeIterator(nil, split...)
   396  		}
   397  		iter := newInternalIterAdapter(newInvalidatingIter(newFunc(iters...)))
   398  		iter.First()
   399  
   400  		j := 0
   401  		for ; iter.Valid() && j < len(testKeyValuePairs); j++ {
   402  			got := fmt.Sprintf("%s:%d", iter.Key().UserKey, iter.Key().SeqNum())
   403  			want := testKeyValuePairs[j]
   404  			if got != want {
   405  				bad = true
   406  				t.Errorf("random splits: i=%d, j=%d: got %q, want %q", i, j, got, want)
   407  			}
   408  			iter.Next()
   409  		}
   410  		if iter.Valid() {
   411  			bad = true
   412  			t.Errorf("random splits: i=%d, j=%d: iter was not exhausted", i, j)
   413  		}
   414  		if j != len(testKeyValuePairs) {
   415  			bad = true
   416  			t.Errorf("random splits: i=%d, j=%d: want j=%d", i, j, len(testKeyValuePairs))
   417  			return
   418  		}
   419  		if err := iter.Close(); err != nil {
   420  			bad = true
   421  			t.Errorf("random splits: i=%d, j=%d: %v", i, j, err)
   422  		}
   423  
   424  		if bad {
   425  			nBad++
   426  			if nBad == 10 {
   427  				t.Fatal("random splits: too many errors; stopping")
   428  			}
   429  		}
   430  	}
   431  }
   432  
   433  // deletableSumValueMerger computes the sum of its arguments,
   434  // but transforms a zero sum into a non-existent entry.
   435  type deletableSumValueMerger struct {
   436  	sum int64
   437  }
   438  
   439  func newDeletableSumValueMerger(key, value []byte) (ValueMerger, error) {
   440  	m := &deletableSumValueMerger{}
   441  	return m, m.MergeNewer(value)
   442  }
   443  
   444  func (m *deletableSumValueMerger) parseAndCalculate(value []byte) error {
   445  	v, err := strconv.ParseInt(string(value), 10, 64)
   446  	if err == nil {
   447  		m.sum += v
   448  	}
   449  	return err
   450  }
   451  
   452  func (m *deletableSumValueMerger) MergeNewer(value []byte) error {
   453  	return m.parseAndCalculate(value)
   454  }
   455  
   456  func (m *deletableSumValueMerger) MergeOlder(value []byte) error {
   457  	return m.parseAndCalculate(value)
   458  }
   459  
   460  func (m *deletableSumValueMerger) Finish(includesBase bool) ([]byte, io.Closer, error) {
   461  	if m.sum == 0 {
   462  		return nil, nil, nil
   463  	}
   464  	return []byte(strconv.FormatInt(m.sum, 10)), nil, nil
   465  }
   466  
   467  func (m *deletableSumValueMerger) DeletableFinish(
   468  	includesBase bool,
   469  ) ([]byte, bool, io.Closer, error) {
   470  	value, closer, err := m.Finish(includesBase)
   471  	return value, len(value) == 0, closer, err
   472  }
   473  
   474  func TestIterator(t *testing.T) {
   475  	var merge Merge
   476  	var keys []InternalKey
   477  	var vals [][]byte
   478  
   479  	newIter := func(seqNum uint64, opts IterOptions) *Iterator {
   480  		if merge == nil {
   481  			merge = DefaultMerger.Merge
   482  		}
   483  		wrappedMerge := func(key, value []byte) (ValueMerger, error) {
   484  			if len(key) == 0 {
   485  				t.Fatalf("an empty key is passed into Merge")
   486  			}
   487  			return merge(key, value)
   488  		}
   489  		it := &Iterator{
   490  			opts:     opts,
   491  			comparer: *testkeys.Comparer,
   492  			merge:    wrappedMerge,
   493  		}
   494  		// NB: Use a mergingIter to filter entries newer than seqNum.
   495  		iter := newMergingIter(nil /* logger */, &it.stats.InternalStats, it.cmp, it.split, &fakeIter{
   496  			lower: opts.GetLowerBound(),
   497  			upper: opts.GetUpperBound(),
   498  			keys:  keys,
   499  			vals:  vals,
   500  		})
   501  		iter.snapshot = seqNum
   502  		iter.elideRangeTombstones = true
   503  		// NB: This Iterator cannot be cloned since it is not constructed
   504  		// with a readState. It suffices for this test.
   505  		it.iter = newInvalidatingIter(iter)
   506  		return it
   507  	}
   508  
   509  	datadriven.RunTest(t, "testdata/iterator", func(d *datadriven.TestData) string {
   510  		switch d.Cmd {
   511  		case "define":
   512  			merge = nil
   513  			if len(d.CmdArgs) > 0 && d.CmdArgs[0].Key == "merger" &&
   514  				len(d.CmdArgs[0].Vals) > 0 && d.CmdArgs[0].Vals[0] == "deletable" {
   515  				merge = newDeletableSumValueMerger
   516  			}
   517  			keys = keys[:0]
   518  			vals = vals[:0]
   519  			for _, key := range strings.Split(d.Input, "\n") {
   520  				j := strings.Index(key, ":")
   521  				keys = append(keys, base.ParseInternalKey(key[:j]))
   522  				vals = append(vals, []byte(key[j+1:]))
   523  			}
   524  			return ""
   525  
   526  		case "iter":
   527  			var seqNum int
   528  			var opts IterOptions
   529  
   530  			for _, arg := range d.CmdArgs {
   531  				if len(arg.Vals) != 1 {
   532  					return fmt.Sprintf("%s: %s=<value>", d.Cmd, arg.Key)
   533  				}
   534  				switch arg.Key {
   535  				case "seq":
   536  					var err error
   537  					seqNum, err = strconv.Atoi(arg.Vals[0])
   538  					if err != nil {
   539  						return err.Error()
   540  					}
   541  				case "lower":
   542  					opts.LowerBound = []byte(arg.Vals[0])
   543  				case "upper":
   544  					opts.UpperBound = []byte(arg.Vals[0])
   545  				default:
   546  					return fmt.Sprintf("%s: unknown arg: %s", d.Cmd, arg.Key)
   547  				}
   548  			}
   549  
   550  			iter := newIter(uint64(seqNum), opts)
   551  			iterOutput := runIterCmd(d, iter, true)
   552  			stats := iter.Stats()
   553  			return fmt.Sprintf("%sstats: %s\n", iterOutput, stats.String())
   554  
   555  		default:
   556  			return fmt.Sprintf("unknown command: %s", d.Cmd)
   557  		}
   558  	})
   559  }
   560  
   561  type minSeqNumPropertyCollector struct {
   562  	minSeqNum uint64
   563  }
   564  
   565  func (c *minSeqNumPropertyCollector) Add(key InternalKey, value []byte) error {
   566  	if c.minSeqNum == 0 || c.minSeqNum > key.SeqNum() {
   567  		c.minSeqNum = key.SeqNum()
   568  	}
   569  	return nil
   570  }
   571  
   572  func (c *minSeqNumPropertyCollector) Finish(userProps map[string]string) error {
   573  	userProps["test.min-seq-num"] = fmt.Sprint(c.minSeqNum)
   574  	return nil
   575  }
   576  
   577  func (c *minSeqNumPropertyCollector) Name() string {
   578  	return "minSeqNumPropertyCollector"
   579  }
   580  
   581  func TestReadSampling(t *testing.T) {
   582  	var d *DB
   583  	defer func() {
   584  		if d != nil {
   585  			require.NoError(t, d.Close())
   586  		}
   587  	}()
   588  
   589  	var iter *Iterator
   590  	defer func() {
   591  		if iter != nil {
   592  			require.NoError(t, iter.Close())
   593  		}
   594  	}()
   595  
   596  	datadriven.RunTest(t, "testdata/iterator_read_sampling", func(td *datadriven.TestData) string {
   597  		switch td.Cmd {
   598  		case "define":
   599  			if iter != nil {
   600  				if err := iter.Close(); err != nil {
   601  					return err.Error()
   602  				}
   603  			}
   604  			if d != nil {
   605  				if err := d.Close(); err != nil {
   606  					return err.Error()
   607  				}
   608  			}
   609  
   610  			opts := &Options{}
   611  			opts.TablePropertyCollectors = append(opts.TablePropertyCollectors,
   612  				func() TablePropertyCollector {
   613  					return &minSeqNumPropertyCollector{}
   614  				})
   615  
   616  			var err error
   617  			if d, err = runDBDefineCmd(td, opts); err != nil {
   618  				return err.Error()
   619  			}
   620  
   621  			d.mu.Lock()
   622  			// Disable the "dynamic base level" code for this test.
   623  			// d.mu.versions.picker.forceBaseLevel1()
   624  			s := d.mu.versions.currentVersion().String()
   625  			d.mu.Unlock()
   626  			return s
   627  
   628  		case "set":
   629  			if d == nil {
   630  				return fmt.Sprintf("%s: db is not defined", td.Cmd)
   631  			}
   632  
   633  			var allowedSeeks int64
   634  
   635  			for _, arg := range td.CmdArgs {
   636  				if len(arg.Vals) != 1 {
   637  					return fmt.Sprintf("%s: %s=<value>", td.Cmd, arg.Key)
   638  				}
   639  				switch arg.Key {
   640  				case "allowed-seeks":
   641  					var err error
   642  					allowedSeeks, err = strconv.ParseInt(arg.Vals[0], 10, 64)
   643  					if err != nil {
   644  						return err.Error()
   645  					}
   646  				}
   647  			}
   648  
   649  			d.mu.Lock()
   650  			for _, l := range d.mu.versions.currentVersion().Levels {
   651  				l.Slice().Each(func(f *fileMetadata) {
   652  					atomic.StoreInt64(&f.Atomic.AllowedSeeks, allowedSeeks)
   653  				})
   654  			}
   655  			d.mu.Unlock()
   656  			return ""
   657  
   658  		case "show":
   659  			if d == nil {
   660  				return fmt.Sprintf("%s: db is not defined", td.Cmd)
   661  			}
   662  
   663  			var fileNum int64
   664  			for _, arg := range td.CmdArgs {
   665  				if len(arg.Vals) != 2 {
   666  					return fmt.Sprintf("%s: %s=<value>", td.Cmd, arg.Key)
   667  				}
   668  				switch arg.Key {
   669  				case "allowed-seeks":
   670  					var err error
   671  					fileNum, err = strconv.ParseInt(arg.Vals[0], 10, 64)
   672  					if err != nil {
   673  						return err.Error()
   674  					}
   675  				}
   676  			}
   677  
   678  			var foundAllowedSeeks int64 = -1
   679  			d.mu.Lock()
   680  			for _, l := range d.mu.versions.currentVersion().Levels {
   681  				l.Slice().Each(func(f *fileMetadata) {
   682  					if f.FileNum == base.FileNum(fileNum) {
   683  						actualAllowedSeeks := atomic.LoadInt64(&f.Atomic.AllowedSeeks)
   684  						foundAllowedSeeks = actualAllowedSeeks
   685  					}
   686  				})
   687  			}
   688  			d.mu.Unlock()
   689  
   690  			if foundAllowedSeeks == -1 {
   691  				return fmt.Sprintf("invalid file num: %d", fileNum)
   692  			}
   693  			return fmt.Sprintf("%d", foundAllowedSeeks)
   694  
   695  		case "iter":
   696  			if iter == nil || iter.iter == nil {
   697  				// TODO(peter): runDBDefineCmd doesn't properly update the visible
   698  				// sequence number. So we have to use a snapshot with a very large
   699  				// sequence number, otherwise the DB appears empty.
   700  				snap := Snapshot{
   701  					db:     d,
   702  					seqNum: InternalKeySeqNumMax,
   703  				}
   704  				iter = snap.NewIter(nil)
   705  				iter.readSampling.forceReadSampling = true
   706  			}
   707  			return runIterCmd(td, iter, false)
   708  
   709  		case "read-compactions":
   710  			if d == nil {
   711  				return fmt.Sprintf("%s: db is not defined", td.Cmd)
   712  			}
   713  
   714  			d.mu.Lock()
   715  			var sb strings.Builder
   716  			if d.mu.compact.readCompactions.size == 0 {
   717  				sb.WriteString("(none)")
   718  			}
   719  			for i := 0; i < d.mu.compact.readCompactions.size; i++ {
   720  				rc := d.mu.compact.readCompactions.at(i)
   721  				sb.WriteString(fmt.Sprintf("(level: %d, start: %s, end: %s)\n", rc.level, string(rc.start), string(rc.end)))
   722  			}
   723  			d.mu.Unlock()
   724  			return sb.String()
   725  
   726  		case "iter-read-compactions":
   727  			if iter == nil {
   728  				return fmt.Sprintf("%s: iter is not defined", td.Cmd)
   729  			}
   730  
   731  			var sb strings.Builder
   732  			if iter.readSampling.pendingCompactions.size == 0 {
   733  				sb.WriteString("(none)")
   734  			}
   735  			for i := 0; i < iter.readSampling.pendingCompactions.size; i++ {
   736  				rc := iter.readSampling.pendingCompactions.at(i)
   737  				sb.WriteString(fmt.Sprintf("(level: %d, start: %s, end: %s)\n", rc.level, string(rc.start), string(rc.end)))
   738  			}
   739  			return sb.String()
   740  
   741  		case "close-iter":
   742  			if iter != nil {
   743  				if err := iter.Close(); err != nil {
   744  					return err.Error()
   745  				}
   746  			}
   747  			return ""
   748  
   749  		default:
   750  			return fmt.Sprintf("unknown command: %s", td.Cmd)
   751  		}
   752  	})
   753  }
   754  
   755  func TestIteratorTableFilter(t *testing.T) {
   756  	var d *DB
   757  	defer func() {
   758  		if d != nil {
   759  			require.NoError(t, d.Close())
   760  		}
   761  	}()
   762  
   763  	datadriven.RunTest(t, "testdata/iterator_table_filter", func(td *datadriven.TestData) string {
   764  		switch td.Cmd {
   765  		case "define":
   766  			if d != nil {
   767  				if err := d.Close(); err != nil {
   768  					return err.Error()
   769  				}
   770  			}
   771  
   772  			opts := &Options{}
   773  			opts.TablePropertyCollectors = append(opts.TablePropertyCollectors,
   774  				func() TablePropertyCollector {
   775  					return &minSeqNumPropertyCollector{}
   776  				})
   777  
   778  			var err error
   779  			if d, err = runDBDefineCmd(td, opts); err != nil {
   780  				return err.Error()
   781  			}
   782  
   783  			d.mu.Lock()
   784  			// Disable the "dynamic base level" code for this test.
   785  			d.mu.versions.picker.forceBaseLevel1()
   786  			s := d.mu.versions.currentVersion().String()
   787  			d.mu.Unlock()
   788  			return s
   789  
   790  		case "iter":
   791  			// We're using an iterator table filter to approximate what is done by
   792  			// snapshots.
   793  			iterOpts := &IterOptions{}
   794  			for _, arg := range td.CmdArgs {
   795  				if len(arg.Vals) != 1 {
   796  					return fmt.Sprintf("%s: %s=<value>", td.Cmd, arg.Key)
   797  				}
   798  				switch arg.Key {
   799  				case "filter":
   800  					seqNum, err := strconv.ParseUint(arg.Vals[0], 10, 64)
   801  					if err != nil {
   802  						return err.Error()
   803  					}
   804  					iterOpts.TableFilter = func(userProps map[string]string) bool {
   805  						minSeqNum, err := strconv.ParseUint(userProps["test.min-seq-num"], 10, 64)
   806  						if err != nil {
   807  							return true
   808  						}
   809  						return minSeqNum < seqNum
   810  					}
   811  				default:
   812  					return fmt.Sprintf("%s: unknown arg: %s", td.Cmd, arg.Key)
   813  				}
   814  			}
   815  
   816  			// TODO(peter): runDBDefineCmd doesn't properly update the visible
   817  			// sequence number. So we have to use a snapshot with a very large
   818  			// sequence number, otherwise the DB appears empty.
   819  			snap := Snapshot{
   820  				db:     d,
   821  				seqNum: InternalKeySeqNumMax,
   822  			}
   823  			iter := snap.NewIter(iterOpts)
   824  			return runIterCmd(td, iter, true)
   825  
   826  		default:
   827  			return fmt.Sprintf("unknown command: %s", td.Cmd)
   828  		}
   829  	})
   830  }
   831  
   832  func TestIteratorNextPrev(t *testing.T) {
   833  	var mem vfs.FS
   834  	var d *DB
   835  	defer func() {
   836  		require.NoError(t, d.Close())
   837  	}()
   838  
   839  	reset := func() {
   840  		if d != nil {
   841  			require.NoError(t, d.Close())
   842  		}
   843  
   844  		mem = vfs.NewMem()
   845  		require.NoError(t, mem.MkdirAll("ext", 0755))
   846  		opts := &Options{FS: mem}
   847  		// Automatic compactions may compact away tombstones from L6, making
   848  		// some testcases non-deterministic.
   849  		opts.DisableAutomaticCompactions = true
   850  		var err error
   851  		d, err = Open("", opts)
   852  		require.NoError(t, err)
   853  	}
   854  	reset()
   855  
   856  	datadriven.RunTest(t, "testdata/iterator_next_prev", func(td *datadriven.TestData) string {
   857  		switch td.Cmd {
   858  		case "reset":
   859  			reset()
   860  			return ""
   861  
   862  		case "build":
   863  			if err := runBuildCmd(td, d, mem); err != nil {
   864  				return err.Error()
   865  			}
   866  			return ""
   867  
   868  		case "ingest":
   869  			if err := runIngestCmd(td, d, mem); err != nil {
   870  				return err.Error()
   871  			}
   872  			return runLSMCmd(td, d)
   873  
   874  		case "iter":
   875  			seqNum := InternalKeySeqNumMax
   876  			for _, arg := range td.CmdArgs {
   877  				if len(arg.Vals) != 1 {
   878  					return fmt.Sprintf("%s: %s=<value>", td.Cmd, arg.Key)
   879  				}
   880  				switch arg.Key {
   881  				case "seq":
   882  					var err error
   883  					seqNum, err = strconv.ParseUint(arg.Vals[0], 10, 64)
   884  					if err != nil {
   885  						return err.Error()
   886  					}
   887  				default:
   888  					return fmt.Sprintf("%s: unknown arg: %s", td.Cmd, arg.Key)
   889  				}
   890  			}
   891  
   892  			snap := Snapshot{
   893  				db:     d,
   894  				seqNum: seqNum,
   895  			}
   896  			iter := snap.NewIter(nil)
   897  			return runIterCmd(td, iter, true)
   898  
   899  		default:
   900  			return fmt.Sprintf("unknown command: %s", td.Cmd)
   901  		}
   902  	})
   903  }
   904  
   905  func TestIteratorStats(t *testing.T) {
   906  	var mem vfs.FS
   907  	var d *DB
   908  	defer func() {
   909  		require.NoError(t, d.Close())
   910  	}()
   911  
   912  	reset := func() {
   913  		if d != nil {
   914  			require.NoError(t, d.Close())
   915  		}
   916  
   917  		mem = vfs.NewMem()
   918  		require.NoError(t, mem.MkdirAll("ext", 0755))
   919  		opts := &Options{FS: mem}
   920  		// Automatic compactions may make some testcases non-deterministic.
   921  		opts.DisableAutomaticCompactions = true
   922  		var err error
   923  		d, err = Open("", opts)
   924  		require.NoError(t, err)
   925  	}
   926  	reset()
   927  
   928  	datadriven.RunTest(t, "testdata/iterator_stats", func(td *datadriven.TestData) string {
   929  		switch td.Cmd {
   930  		case "reset":
   931  			reset()
   932  			return ""
   933  
   934  		case "build":
   935  			if err := runBuildCmd(td, d, mem); err != nil {
   936  				return err.Error()
   937  			}
   938  			return ""
   939  
   940  		case "ingest":
   941  			if err := runIngestCmd(td, d, mem); err != nil {
   942  				return err.Error()
   943  			}
   944  			return runLSMCmd(td, d)
   945  
   946  		case "iter":
   947  			seqNum := InternalKeySeqNumMax
   948  			for _, arg := range td.CmdArgs {
   949  				if len(arg.Vals) != 1 {
   950  					return fmt.Sprintf("%s: %s=<value>", td.Cmd, arg.Key)
   951  				}
   952  				switch arg.Key {
   953  				case "seq":
   954  					var err error
   955  					seqNum, err = strconv.ParseUint(arg.Vals[0], 10, 64)
   956  					if err != nil {
   957  						return err.Error()
   958  					}
   959  				default:
   960  					return fmt.Sprintf("%s: unknown arg: %s", td.Cmd, arg.Key)
   961  				}
   962  			}
   963  
   964  			snap := Snapshot{
   965  				db:     d,
   966  				seqNum: seqNum,
   967  			}
   968  			iter := snap.NewIter(nil)
   969  			return runIterCmd(td, iter, true)
   970  
   971  		default:
   972  			return fmt.Sprintf("unknown command: %s", td.Cmd)
   973  		}
   974  	})
   975  }
   976  
   977  type iterSeekOptWrapper struct {
   978  	internalIterator
   979  
   980  	seekGEUsingNext, seekPrefixGEUsingNext *int
   981  }
   982  
   983  func (i *iterSeekOptWrapper) SeekGE(key []byte, flags base.SeekGEFlags) (*InternalKey, []byte) {
   984  	if flags.TrySeekUsingNext() {
   985  		*i.seekGEUsingNext++
   986  	}
   987  	return i.internalIterator.SeekGE(key, flags)
   988  }
   989  
   990  func (i *iterSeekOptWrapper) SeekPrefixGE(
   991  	prefix, key []byte, flags base.SeekGEFlags,
   992  ) (*InternalKey, []byte) {
   993  	if flags.TrySeekUsingNext() {
   994  		*i.seekPrefixGEUsingNext++
   995  	}
   996  	return i.internalIterator.SeekPrefixGE(prefix, key, flags)
   997  }
   998  
   999  func TestIteratorSeekOpt(t *testing.T) {
  1000  	var d *DB
  1001  	defer func() {
  1002  		require.NoError(t, d.Close())
  1003  	}()
  1004  	var iter *Iterator
  1005  	defer func() {
  1006  		if iter != nil {
  1007  			require.NoError(t, iter.Close())
  1008  		}
  1009  	}()
  1010  	var seekGEUsingNext, seekPrefixGEUsingNext int
  1011  
  1012  	datadriven.RunTest(t, "testdata/iterator_seek_opt", func(td *datadriven.TestData) string {
  1013  		switch td.Cmd {
  1014  		case "define":
  1015  			if iter != nil {
  1016  				if err := iter.Close(); err != nil {
  1017  					return err.Error()
  1018  				}
  1019  			}
  1020  			if d != nil {
  1021  				if err := d.Close(); err != nil {
  1022  					return err.Error()
  1023  				}
  1024  			}
  1025  			seekGEUsingNext = 0
  1026  			seekPrefixGEUsingNext = 0
  1027  
  1028  			opts := &Options{}
  1029  			opts.TablePropertyCollectors = append(opts.TablePropertyCollectors,
  1030  				func() TablePropertyCollector {
  1031  					return &minSeqNumPropertyCollector{}
  1032  				})
  1033  
  1034  			var err error
  1035  			if d, err = runDBDefineCmd(td, opts); err != nil {
  1036  				return err.Error()
  1037  			}
  1038  
  1039  			d.mu.Lock()
  1040  			s := d.mu.versions.currentVersion().String()
  1041  			d.mu.Unlock()
  1042  			oldNewIters := d.newIters
  1043  			d.newIters = func(file *manifest.FileMetadata, opts *IterOptions, internalOpts internalIterOpts) (internalIterator, keyspan.FragmentIterator, error) {
  1044  				iter, rangeIter, err := oldNewIters(file, opts, internalOpts)
  1045  				iterWrapped := &iterSeekOptWrapper{
  1046  					internalIterator:      iter,
  1047  					seekGEUsingNext:       &seekGEUsingNext,
  1048  					seekPrefixGEUsingNext: &seekPrefixGEUsingNext,
  1049  				}
  1050  				return iterWrapped, rangeIter, err
  1051  			}
  1052  			return s
  1053  
  1054  		case "iter":
  1055  			if iter == nil || iter.iter == nil {
  1056  				// TODO(peter): runDBDefineCmd doesn't properly update the visible
  1057  				// sequence number. So we have to use a snapshot with a very large
  1058  				// sequence number, otherwise the DB appears empty.
  1059  				snap := Snapshot{
  1060  					db:     d,
  1061  					seqNum: InternalKeySeqNumMax,
  1062  				}
  1063  				iter = snap.NewIter(nil)
  1064  				iter.readSampling.forceReadSampling = true
  1065  				iter.comparer.Split = func(a []byte) int { return len(a) }
  1066  				iter.forceEnableSeekOpt = true
  1067  			}
  1068  			iterOutput := runIterCmd(td, iter, false)
  1069  			stats := iter.Stats()
  1070  			// InternalStats are non-deterministic since they depend on how data is
  1071  			// distributed across memtables and sstables in the DB.
  1072  			stats.InternalStats = InternalIteratorStats{}
  1073  			var builder strings.Builder
  1074  			fmt.Fprintf(&builder, "%sstats: %s\n", iterOutput, stats.String())
  1075  			fmt.Fprintf(&builder, "SeekGEs with trySeekUsingNext: %d\n", seekGEUsingNext)
  1076  			fmt.Fprintf(&builder, "SeekPrefixGEs with trySeekUsingNext: %d\n", seekPrefixGEUsingNext)
  1077  			return builder.String()
  1078  
  1079  		default:
  1080  			return fmt.Sprintf("unknown command: %s", td.Cmd)
  1081  		}
  1082  	})
  1083  }
  1084  
  1085  type errorSeekIter struct {
  1086  	internalIterator
  1087  	// Fields controlling error injection for seeks.
  1088  	injectSeekErrorCounts []int
  1089  	seekCount             int
  1090  	err                   error
  1091  }
  1092  
  1093  func (i *errorSeekIter) SeekGE(key []byte, flags base.SeekGEFlags) (*InternalKey, []byte) {
  1094  	if i.tryInjectError() {
  1095  		return nil, nil
  1096  	}
  1097  	i.err = nil
  1098  	i.seekCount++
  1099  	return i.internalIterator.SeekGE(key, flags)
  1100  }
  1101  
  1102  func (i *errorSeekIter) SeekPrefixGE(
  1103  	prefix, key []byte, flags base.SeekGEFlags,
  1104  ) (*InternalKey, []byte) {
  1105  	if i.tryInjectError() {
  1106  		return nil, nil
  1107  	}
  1108  	i.err = nil
  1109  	i.seekCount++
  1110  	return i.internalIterator.SeekPrefixGE(prefix, key, flags)
  1111  }
  1112  
  1113  func (i *errorSeekIter) SeekLT(key []byte, flags base.SeekLTFlags) (*InternalKey, []byte) {
  1114  	if i.tryInjectError() {
  1115  		return nil, nil
  1116  	}
  1117  	i.err = nil
  1118  	i.seekCount++
  1119  	return i.internalIterator.SeekLT(key, flags)
  1120  }
  1121  
  1122  func (i *errorSeekIter) tryInjectError() bool {
  1123  	if len(i.injectSeekErrorCounts) > 0 && i.injectSeekErrorCounts[0] == i.seekCount {
  1124  		i.seekCount++
  1125  		i.err = errors.Errorf("injecting error")
  1126  		i.injectSeekErrorCounts = i.injectSeekErrorCounts[1:]
  1127  		return true
  1128  	}
  1129  	return false
  1130  }
  1131  
  1132  func (i *errorSeekIter) First() (*InternalKey, []byte) {
  1133  	i.err = nil
  1134  	return i.internalIterator.First()
  1135  }
  1136  
  1137  func (i *errorSeekIter) Last() (*InternalKey, []byte) {
  1138  	i.err = nil
  1139  	return i.internalIterator.Last()
  1140  }
  1141  
  1142  func (i *errorSeekIter) Next() (*InternalKey, []byte) {
  1143  	if i.err != nil {
  1144  		return nil, nil
  1145  	}
  1146  	return i.internalIterator.Next()
  1147  }
  1148  
  1149  func (i *errorSeekIter) Prev() (*InternalKey, []byte) {
  1150  	if i.err != nil {
  1151  		return nil, nil
  1152  	}
  1153  	return i.internalIterator.Prev()
  1154  }
  1155  
  1156  func (i *errorSeekIter) Error() error {
  1157  	if i.err != nil {
  1158  		return i.err
  1159  	}
  1160  	return i.internalIterator.Error()
  1161  }
  1162  
  1163  func TestIteratorSeekOptErrors(t *testing.T) {
  1164  	var keys []InternalKey
  1165  	var vals [][]byte
  1166  
  1167  	var errorIter errorSeekIter
  1168  	newIter := func(opts IterOptions) *Iterator {
  1169  		iter := &fakeIter{
  1170  			lower: opts.GetLowerBound(),
  1171  			upper: opts.GetUpperBound(),
  1172  			keys:  keys,
  1173  			vals:  vals,
  1174  		}
  1175  		errorIter = errorSeekIter{internalIterator: newInvalidatingIter(iter)}
  1176  		// NB: This Iterator cannot be cloned since it is not constructed
  1177  		// with a readState. It suffices for this test.
  1178  		return &Iterator{
  1179  			opts:     opts,
  1180  			comparer: *testkeys.Comparer,
  1181  			merge:    DefaultMerger.Merge,
  1182  			iter:     &errorIter,
  1183  		}
  1184  	}
  1185  
  1186  	datadriven.RunTest(t, "testdata/iterator_seek_opt_errors", func(d *datadriven.TestData) string {
  1187  		switch d.Cmd {
  1188  		case "define":
  1189  			keys = keys[:0]
  1190  			vals = vals[:0]
  1191  			for _, key := range strings.Split(d.Input, "\n") {
  1192  				j := strings.Index(key, ":")
  1193  				keys = append(keys, base.ParseInternalKey(key[:j]))
  1194  				vals = append(vals, []byte(key[j+1:]))
  1195  			}
  1196  			return ""
  1197  
  1198  		case "iter":
  1199  			var opts IterOptions
  1200  			var injectSeekGEErrorCounts []int
  1201  			for _, arg := range d.CmdArgs {
  1202  				if len(arg.Vals) < 1 {
  1203  					return fmt.Sprintf("%s: %s=<value>", d.Cmd, arg.Key)
  1204  				}
  1205  				switch arg.Key {
  1206  				case "lower":
  1207  					opts.LowerBound = []byte(arg.Vals[0])
  1208  				case "upper":
  1209  					opts.UpperBound = []byte(arg.Vals[0])
  1210  				case "seek-error":
  1211  					for i := 0; i < len(arg.Vals); i++ {
  1212  						n, err := strconv.Atoi(arg.Vals[i])
  1213  						if err != nil {
  1214  							return err.Error()
  1215  						}
  1216  						injectSeekGEErrorCounts = append(injectSeekGEErrorCounts, n)
  1217  					}
  1218  				default:
  1219  					return fmt.Sprintf("%s: unknown arg: %s", d.Cmd, arg.Key)
  1220  				}
  1221  			}
  1222  
  1223  			iter := newIter(opts)
  1224  			errorIter.injectSeekErrorCounts = injectSeekGEErrorCounts
  1225  			return runIterCmd(d, iter, true)
  1226  
  1227  		default:
  1228  			return fmt.Sprintf("unknown command: %s", d.Cmd)
  1229  		}
  1230  	})
  1231  }
  1232  
  1233  type testBlockIntervalCollector struct {
  1234  	numLength     int
  1235  	offsetFromEnd int
  1236  	initialized   bool
  1237  	lower, upper  uint64
  1238  }
  1239  
  1240  func (bi *testBlockIntervalCollector) Add(key InternalKey, value []byte) error {
  1241  	k := key.UserKey
  1242  	if len(k) < bi.numLength+bi.offsetFromEnd {
  1243  		return nil
  1244  	}
  1245  	n := len(k) - bi.offsetFromEnd - bi.numLength
  1246  	val, err := strconv.Atoi(string(k[n : n+bi.numLength]))
  1247  	if err != nil {
  1248  		return err
  1249  	}
  1250  	if val < 0 {
  1251  		panic("testBlockIntervalCollector expects values >= 0")
  1252  	}
  1253  	uval := uint64(val)
  1254  	if !bi.initialized {
  1255  		bi.lower, bi.upper = uval, uval+1
  1256  		bi.initialized = true
  1257  		return nil
  1258  	}
  1259  	if bi.lower > uval {
  1260  		bi.lower = uval
  1261  	}
  1262  	if uval >= bi.upper {
  1263  		bi.upper = uval + 1
  1264  	}
  1265  	return nil
  1266  }
  1267  
  1268  func (bi *testBlockIntervalCollector) FinishDataBlock() (lower uint64, upper uint64, err error) {
  1269  	bi.initialized = false
  1270  	l, u := bi.lower, bi.upper
  1271  	bi.lower, bi.upper = 0, 0
  1272  	return l, u, nil
  1273  }
  1274  
  1275  func TestIteratorBlockIntervalFilter(t *testing.T) {
  1276  	var mem vfs.FS
  1277  	var d *DB
  1278  	defer func() {
  1279  		require.NoError(t, d.Close())
  1280  	}()
  1281  
  1282  	type collector struct {
  1283  		id     uint16
  1284  		offset int
  1285  	}
  1286  	createDB := func(collectors []collector) {
  1287  		if d != nil {
  1288  			require.NoError(t, d.Close())
  1289  		}
  1290  
  1291  		mem = vfs.NewMem()
  1292  		require.NoError(t, mem.MkdirAll("ext", 0755))
  1293  
  1294  		var bpCollectors []func() BlockPropertyCollector
  1295  		for _, c := range collectors {
  1296  			coll := c
  1297  			bpCollectors = append(bpCollectors, func() BlockPropertyCollector {
  1298  				return sstable.NewBlockIntervalCollector(
  1299  					fmt.Sprintf("%d", coll.id),
  1300  					&testBlockIntervalCollector{numLength: 2, offsetFromEnd: coll.offset},
  1301  					nil, /* range key collector */
  1302  				)
  1303  			})
  1304  		}
  1305  		opts := &Options{
  1306  			FS:                      mem,
  1307  			FormatMajorVersion:      FormatNewest,
  1308  			BlockPropertyCollectors: bpCollectors,
  1309  		}
  1310  		lo := LevelOptions{BlockSize: 1, IndexBlockSize: 1}
  1311  		opts.Levels = append(opts.Levels, lo)
  1312  
  1313  		// Automatic compactions may compact away tombstones from L6, making
  1314  		// some testcases non-deterministic.
  1315  		opts.DisableAutomaticCompactions = true
  1316  		var err error
  1317  		d, err = Open("", opts)
  1318  		require.NoError(t, err)
  1319  	}
  1320  
  1321  	datadriven.RunTest(
  1322  		t, "testdata/iterator_block_interval_filter", func(td *datadriven.TestData) string {
  1323  			switch td.Cmd {
  1324  			case "build":
  1325  				var collectors []collector
  1326  				for _, arg := range td.CmdArgs {
  1327  					switch arg.Key {
  1328  					case "id_offset":
  1329  						if len(arg.Vals) != 2 {
  1330  							return "id and offset not provided"
  1331  						}
  1332  						var id, offset int
  1333  						var err error
  1334  						if id, err = strconv.Atoi(arg.Vals[0]); err != nil {
  1335  							return err.Error()
  1336  						}
  1337  						if offset, err = strconv.Atoi(arg.Vals[1]); err != nil {
  1338  							return err.Error()
  1339  						}
  1340  						collectors = append(collectors, collector{id: uint16(id), offset: offset})
  1341  					default:
  1342  						return fmt.Sprintf("unknown key: %s", arg.Key)
  1343  					}
  1344  				}
  1345  				createDB(collectors)
  1346  				b := d.NewBatch()
  1347  				if err := runBatchDefineCmd(td, b); err != nil {
  1348  					return err.Error()
  1349  				}
  1350  				if err := b.Commit(nil); err != nil {
  1351  					return err.Error()
  1352  				}
  1353  				if err := d.Flush(); err != nil {
  1354  					return err.Error()
  1355  				}
  1356  				return runLSMCmd(td, d)
  1357  
  1358  			case "iter":
  1359  				var opts IterOptions
  1360  				for _, arg := range td.CmdArgs {
  1361  					switch arg.Key {
  1362  					case "id_lower_upper":
  1363  						if len(arg.Vals) != 3 {
  1364  							return "id, lower, upper not provided"
  1365  						}
  1366  						var id, lower, upper int
  1367  						var err error
  1368  						if id, err = strconv.Atoi(arg.Vals[0]); err != nil {
  1369  							return err.Error()
  1370  						}
  1371  						if lower, err = strconv.Atoi(arg.Vals[1]); err != nil {
  1372  							return err.Error()
  1373  						}
  1374  						if upper, err = strconv.Atoi(arg.Vals[2]); err != nil {
  1375  							return err.Error()
  1376  						}
  1377  						opts.PointKeyFilters = append(opts.PointKeyFilters,
  1378  							sstable.NewBlockIntervalFilter(fmt.Sprintf("%d", id),
  1379  								uint64(lower), uint64(upper)))
  1380  					default:
  1381  						return fmt.Sprintf("unknown key: %s", arg.Key)
  1382  					}
  1383  				}
  1384  				rand.Shuffle(len(opts.PointKeyFilters), func(i, j int) {
  1385  					opts.PointKeyFilters[i], opts.PointKeyFilters[j] =
  1386  						opts.PointKeyFilters[j], opts.PointKeyFilters[i]
  1387  				})
  1388  				iter := d.NewIter(&opts)
  1389  				return runIterCmd(td, iter, true)
  1390  
  1391  			default:
  1392  				return fmt.Sprintf("unknown command: %s", td.Cmd)
  1393  			}
  1394  		})
  1395  }
  1396  
  1397  var seed = flag.Uint64("seed", 0, "a pseudorandom number generator seed")
  1398  
  1399  func randStr(fill []byte, rng *rand.Rand) {
  1400  	const letters = "abcdefghijklmnopqrstuvwxyz"
  1401  	const lettersLen = len(letters)
  1402  	for i := 0; i < len(fill); i++ {
  1403  		fill[i] = letters[rng.Intn(lettersLen)]
  1404  	}
  1405  }
  1406  
  1407  func randValue(n int, rng *rand.Rand) []byte {
  1408  	buf := make([]byte, n)
  1409  	randStr(buf, rng)
  1410  	return buf
  1411  }
  1412  
  1413  func randKey(n int, rng *rand.Rand) ([]byte, int) {
  1414  	keyPrefix := randValue(n, rng)
  1415  	suffix := rng.Intn(100)
  1416  	return append(keyPrefix, []byte(fmt.Sprintf("%02d", suffix))...), suffix
  1417  }
  1418  
  1419  func TestIteratorRandomizedBlockIntervalFilter(t *testing.T) {
  1420  	mem := vfs.NewMem()
  1421  	opts := &Options{
  1422  		FS:                 mem,
  1423  		FormatMajorVersion: FormatNewest,
  1424  		BlockPropertyCollectors: []func() BlockPropertyCollector{
  1425  			func() BlockPropertyCollector {
  1426  				return sstable.NewBlockIntervalCollector(
  1427  					"0", &testBlockIntervalCollector{numLength: 2}, nil, /* range key collector */
  1428  				)
  1429  			},
  1430  		},
  1431  	}
  1432  	seed := *seed
  1433  	if seed == 0 {
  1434  		seed = uint64(time.Now().UnixNano())
  1435  		fmt.Printf("seed: %d\n", seed)
  1436  	}
  1437  	rng := rand.New(rand.NewSource(seed))
  1438  	opts.FlushSplitBytes = 1 << rng.Intn(8)            // 1B - 256B
  1439  	opts.L0CompactionThreshold = 1 << rng.Intn(2)      // 1-2
  1440  	opts.L0CompactionFileThreshold = 1 << rng.Intn(11) // 1-1024
  1441  	opts.LBaseMaxBytes = 1 << rng.Intn(11)             // 1B - 1KB
  1442  	opts.MemTableSize = 2 << 10                        // 2KB
  1443  	var lopts LevelOptions
  1444  	lopts.BlockSize = 1 << rng.Intn(8)      // 1B - 256B
  1445  	lopts.IndexBlockSize = 1 << rng.Intn(8) // 1B - 256B
  1446  	opts.Levels = []LevelOptions{lopts}
  1447  
  1448  	d, err := Open("", opts)
  1449  	require.NoError(t, err)
  1450  	defer func() {
  1451  		require.NoError(t, d.Close())
  1452  	}()
  1453  	matchingKeyValues := make(map[string]string)
  1454  	lower := rng.Intn(100)
  1455  	upper := rng.Intn(100)
  1456  	if lower > upper {
  1457  		lower, upper = upper, lower
  1458  	}
  1459  	n := 2000
  1460  	for i := 0; i < n; i++ {
  1461  		key, suffix := randKey(20+rng.Intn(5), rng)
  1462  		value := randValue(50, rng)
  1463  		if lower <= suffix && suffix < upper {
  1464  			matchingKeyValues[string(key)] = string(value)
  1465  		}
  1466  		d.Set(key, value, nil)
  1467  	}
  1468  
  1469  	var iterOpts IterOptions
  1470  	iterOpts.PointKeyFilters = []BlockPropertyFilter{
  1471  		sstable.NewBlockIntervalFilter("0",
  1472  			uint64(lower), uint64(upper)),
  1473  	}
  1474  	iter := d.NewIter(&iterOpts)
  1475  	defer func() {
  1476  		require.NoError(t, iter.Close())
  1477  	}()
  1478  	iter.First()
  1479  	found := 0
  1480  	matchingCount := len(matchingKeyValues)
  1481  	for ; iter.Valid(); iter.Next() {
  1482  		found++
  1483  		key := string(iter.Key())
  1484  		value, ok := matchingKeyValues[key]
  1485  		if ok {
  1486  			require.Equal(t, value, string(iter.Value()))
  1487  			delete(matchingKeyValues, key)
  1488  		}
  1489  	}
  1490  	fmt.Printf("generated %d keys: %d matching, %d found\n", n, matchingCount, found)
  1491  	require.Equal(t, 0, len(matchingKeyValues))
  1492  }
  1493  
  1494  func TestIteratorGuaranteedDurable(t *testing.T) {
  1495  	mem := vfs.NewMem()
  1496  	opts := &Options{FS: mem}
  1497  	d, err := Open("", opts)
  1498  	require.NoError(t, err)
  1499  	defer func() {
  1500  		require.NoError(t, d.Close())
  1501  	}()
  1502  	iterOptions := IterOptions{OnlyReadGuaranteedDurable: true}
  1503  	failFunc := func(t *testing.T, reader Reader) {
  1504  		defer func() {
  1505  			if r := recover(); r == nil {
  1506  				require.Fail(t, "expected panic")
  1507  			}
  1508  			reader.Close()
  1509  		}()
  1510  		iter := reader.NewIter(&iterOptions)
  1511  		defer iter.Close()
  1512  	}
  1513  	t.Run("snapshot", func(t *testing.T) {
  1514  		failFunc(t, d.NewSnapshot())
  1515  	})
  1516  	t.Run("batch", func(t *testing.T) {
  1517  		failFunc(t, d.NewIndexedBatch())
  1518  	})
  1519  	t.Run("db", func(t *testing.T) {
  1520  		d.Set([]byte("k"), []byte("v"), nil)
  1521  		foundKV := func(o *IterOptions) bool {
  1522  			iter := d.NewIter(o)
  1523  			defer iter.Close()
  1524  			iter.SeekGE([]byte("k"))
  1525  			return iter.Valid()
  1526  		}
  1527  		require.True(t, foundKV(nil))
  1528  		require.False(t, foundKV(&iterOptions))
  1529  		require.NoError(t, d.Flush())
  1530  		require.True(t, foundKV(nil))
  1531  		require.True(t, foundKV(&iterOptions))
  1532  	})
  1533  }
  1534  
  1535  func TestIteratorBoundsLifetimes(t *testing.T) {
  1536  	rng := rand.New(rand.NewSource(uint64(time.Now().UnixNano())))
  1537  	d := newPointTestkeysDatabase(t, testkeys.Alpha(2))
  1538  	defer func() { require.NoError(t, d.Close()) }()
  1539  
  1540  	var buf bytes.Buffer
  1541  	iterators := map[string]*Iterator{}
  1542  	var labels []string
  1543  	printIters := func(w io.Writer) {
  1544  		labels = labels[:0]
  1545  		for label := range iterators {
  1546  			labels = append(labels, label)
  1547  		}
  1548  		sort.Strings(labels)
  1549  		for _, label := range labels {
  1550  			it := iterators[label]
  1551  			fmt.Fprintf(&buf, "%s: (", label)
  1552  			if it.opts.LowerBound == nil {
  1553  				fmt.Fprint(&buf, "<nil>, ")
  1554  			} else {
  1555  				fmt.Fprintf(&buf, "%q, ", it.opts.LowerBound)
  1556  			}
  1557  			if it.opts.UpperBound == nil {
  1558  				fmt.Fprint(&buf, "<nil>)")
  1559  			} else {
  1560  				fmt.Fprintf(&buf, "%q)", it.opts.UpperBound)
  1561  			}
  1562  			fmt.Fprintf(&buf, " boundsBufIdx=%d\n", it.boundsBufIdx)
  1563  		}
  1564  	}
  1565  	parseBounds := func(td *datadriven.TestData) (lower, upper []byte) {
  1566  		for _, arg := range td.CmdArgs {
  1567  			if arg.Key == "lower" {
  1568  				lower = []byte(arg.Vals[0])
  1569  			} else if arg.Key == "upper" {
  1570  				upper = []byte(arg.Vals[0])
  1571  			}
  1572  		}
  1573  		return lower, upper
  1574  	}
  1575  	trashBounds := func(bounds ...[]byte) {
  1576  		for _, bound := range bounds {
  1577  			rng.Read(bound[:])
  1578  		}
  1579  	}
  1580  
  1581  	datadriven.RunTest(t, "testdata/iterator_bounds_lifetimes", func(td *datadriven.TestData) string {
  1582  		switch td.Cmd {
  1583  		case "define":
  1584  			var err error
  1585  			if d, err = runDBDefineCmd(td, d.opts); err != nil {
  1586  				return err.Error()
  1587  			}
  1588  			d.mu.Lock()
  1589  			s := d.mu.versions.currentVersion().String()
  1590  			d.mu.Unlock()
  1591  			return s
  1592  		case "new-iter":
  1593  			var label string
  1594  			td.ScanArgs(t, "label", &label)
  1595  			lower, upper := parseBounds(td)
  1596  			iterators[label] = d.NewIter(&IterOptions{
  1597  				LowerBound: lower,
  1598  				UpperBound: upper,
  1599  			})
  1600  			trashBounds(lower, upper)
  1601  			buf.Reset()
  1602  			printIters(&buf)
  1603  			return buf.String()
  1604  		case "clone":
  1605  			var from, to string
  1606  			td.ScanArgs(t, "from", &from)
  1607  			td.ScanArgs(t, "to", &to)
  1608  			var err error
  1609  			iterators[to], err = iterators[from].Clone(CloneOptions{})
  1610  			if err != nil {
  1611  				return err.Error()
  1612  			}
  1613  			buf.Reset()
  1614  			printIters(&buf)
  1615  			return buf.String()
  1616  		case "close":
  1617  			var label string
  1618  			td.ScanArgs(t, "label", &label)
  1619  			iterators[label].Close()
  1620  			delete(iterators, label)
  1621  			buf.Reset()
  1622  			printIters(&buf)
  1623  			return buf.String()
  1624  		case "iter":
  1625  			var label string
  1626  			td.ScanArgs(t, "label", &label)
  1627  			return runIterCmd(td, iterators[label], false /* closeIter */)
  1628  		case "set-bounds":
  1629  			var label string
  1630  			td.ScanArgs(t, "label", &label)
  1631  			lower, upper := parseBounds(td)
  1632  			iterators[label].SetBounds(lower, upper)
  1633  			trashBounds(lower, upper)
  1634  			buf.Reset()
  1635  			printIters(&buf)
  1636  			return buf.String()
  1637  		case "set-options":
  1638  			var label string
  1639  			var tableFilter bool
  1640  			td.ScanArgs(t, "label", &label)
  1641  			opts := iterators[label].opts
  1642  			for _, arg := range td.CmdArgs {
  1643  				if arg.Key == "table-filter" {
  1644  					tableFilter = true
  1645  				}
  1646  				if arg.Key == "key-types" {
  1647  					switch arg.Vals[0] {
  1648  					case "points-only":
  1649  						opts.KeyTypes = IterKeyTypePointsOnly
  1650  					case "ranges-only":
  1651  						opts.KeyTypes = IterKeyTypeRangesOnly
  1652  					case "both":
  1653  						opts.KeyTypes = IterKeyTypePointsAndRanges
  1654  					default:
  1655  						panic(fmt.Sprintf("unrecognized key type %q", arg.Vals[0]))
  1656  					}
  1657  				}
  1658  			}
  1659  			opts.LowerBound, opts.UpperBound = parseBounds(td)
  1660  			if tableFilter {
  1661  				opts.TableFilter = func(userProps map[string]string) bool { return false }
  1662  			}
  1663  			iterators[label].SetOptions(&opts)
  1664  			trashBounds(opts.LowerBound, opts.UpperBound)
  1665  			buf.Reset()
  1666  			printIters(&buf)
  1667  			return buf.String()
  1668  		default:
  1669  			return fmt.Sprintf("unrecognized command %q", td.Cmd)
  1670  		}
  1671  	})
  1672  }
  1673  
  1674  // TestSetOptionsEquivalence tests equivalence between SetOptions to mutate an
  1675  // iterator and constructing a new iterator with NewIter. The long-lived
  1676  // iterator and the new iterator should surface identical iterator states.
  1677  func TestSetOptionsEquivalence(t *testing.T) {
  1678  	seed := uint64(time.Now().UnixNano())
  1679  	// Call a helper function with the seed so that the seed appears within
  1680  	// stack traces if there's a panic.
  1681  	testSetOptionsEquivalence(t, seed)
  1682  }
  1683  
  1684  func testSetOptionsEquivalence(t *testing.T, seed uint64) {
  1685  	rng := rand.New(rand.NewSource(seed))
  1686  	ks := testkeys.Alpha(2)
  1687  	d := newTestkeysDatabase(t, ks, rng)
  1688  	d.opts.Logger = panicLogger{}
  1689  	defer func() { require.NoError(t, d.Close()) }()
  1690  
  1691  	var o IterOptions
  1692  	generateNewOptions := func() {
  1693  		// TODO(jackson): Include test coverage for block property filters, etc.
  1694  		if rng.Intn(2) == 1 {
  1695  			o.KeyTypes = IterKeyType(rng.Intn(3))
  1696  		}
  1697  		if rng.Intn(2) == 1 {
  1698  			if rng.Intn(2) == 1 {
  1699  				o.LowerBound = nil
  1700  				if rng.Intn(2) == 1 {
  1701  					o.LowerBound = testkeys.KeyAt(ks, rng.Intn(ks.Count()), rng.Intn(ks.Count()))
  1702  				}
  1703  			}
  1704  			if rng.Intn(2) == 1 {
  1705  				o.UpperBound = nil
  1706  				if rng.Intn(2) == 1 {
  1707  					o.UpperBound = testkeys.KeyAt(ks, rng.Intn(ks.Count()), rng.Intn(ks.Count()))
  1708  				}
  1709  			}
  1710  			if testkeys.Comparer.Compare(o.LowerBound, o.UpperBound) > 0 {
  1711  				o.LowerBound, o.UpperBound = o.UpperBound, o.LowerBound
  1712  			}
  1713  		}
  1714  		o.RangeKeyMasking.Suffix = nil
  1715  		if o.KeyTypes == IterKeyTypePointsAndRanges && rng.Intn(2) == 1 {
  1716  			o.RangeKeyMasking.Suffix = testkeys.Suffix(rng.Intn(ks.Count()))
  1717  		}
  1718  	}
  1719  
  1720  	var longLivedIter, newIter *Iterator
  1721  	var history, longLivedBuf, newIterBuf bytes.Buffer
  1722  	defer func() {
  1723  		if r := recover(); r != nil {
  1724  			t.Log(history.String())
  1725  			panic(r)
  1726  		}
  1727  	}()
  1728  	defer func() {
  1729  		if longLivedIter != nil {
  1730  			longLivedIter.Close()
  1731  		}
  1732  		if newIter != nil {
  1733  			newIter.Close()
  1734  		}
  1735  	}()
  1736  
  1737  	type positioningOp struct {
  1738  		desc string
  1739  		run  func(*Iterator) IterValidityState
  1740  	}
  1741  	positioningOps := []func() positioningOp{
  1742  		// SeekGE
  1743  		func() positioningOp {
  1744  			k := testkeys.Key(ks, rng.Intn(ks.Count()))
  1745  			return positioningOp{
  1746  				desc: fmt.Sprintf("SeekGE(%q)", k),
  1747  				run: func(it *Iterator) IterValidityState {
  1748  					return it.SeekGEWithLimit(k, nil)
  1749  				},
  1750  			}
  1751  		},
  1752  		// SeekLT
  1753  		func() positioningOp {
  1754  			k := testkeys.Key(ks, rng.Intn(ks.Count()))
  1755  			return positioningOp{
  1756  				desc: fmt.Sprintf("SeekLT(%q)", k),
  1757  				run: func(it *Iterator) IterValidityState {
  1758  					return it.SeekLTWithLimit(k, nil)
  1759  				},
  1760  			}
  1761  		},
  1762  		// SeekPrefixGE
  1763  		func() positioningOp {
  1764  			k := testkeys.Key(ks, rng.Intn(ks.Count()))
  1765  			return positioningOp{
  1766  				desc: fmt.Sprintf("SeekPrefixGE(%q)", k),
  1767  				run: func(it *Iterator) IterValidityState {
  1768  					if it.SeekPrefixGE(k) {
  1769  						return IterValid
  1770  					}
  1771  					return IterExhausted
  1772  				},
  1773  			}
  1774  		},
  1775  	}
  1776  
  1777  	for i := 0; i < 10_000; i++ {
  1778  		// Generate new random options. The options in o will be mutated.
  1779  		generateNewOptions()
  1780  		fmt.Fprintf(&history, "new options: %s\n", iterOptionsString(&o))
  1781  
  1782  		newIter = d.NewIter(&o)
  1783  		if longLivedIter == nil {
  1784  			longLivedIter = d.NewIter(&o)
  1785  		} else {
  1786  			longLivedIter.SetOptions(&o)
  1787  		}
  1788  
  1789  		// Apply the same operation to both keys.
  1790  		iterOp := positioningOps[rng.Intn(len(positioningOps))]()
  1791  		newIterValidity := iterOp.run(newIter)
  1792  		longLivedValidity := iterOp.run(longLivedIter)
  1793  
  1794  		newIterBuf.Reset()
  1795  		longLivedBuf.Reset()
  1796  		printIterState(&newIterBuf, newIter, newIterValidity, true /* printValidityState */)
  1797  		printIterState(&longLivedBuf, longLivedIter, longLivedValidity, true /* printValidityState */)
  1798  		fmt.Fprintf(&history, "%s = %s\n", iterOp.desc, newIterBuf.String())
  1799  
  1800  		if newIterBuf.String() != longLivedBuf.String() {
  1801  			t.Logf("history:\n%s\n", history.String())
  1802  			t.Logf("seed: %d\n", seed)
  1803  			t.Fatalf("expected %q, got %q", newIterBuf.String(), longLivedBuf.String())
  1804  		}
  1805  		_ = newIter.Close()
  1806  
  1807  		newIter = nil
  1808  	}
  1809  	t.Logf("history:\n%s\n", history.String())
  1810  }
  1811  
  1812  func iterOptionsString(o *IterOptions) string {
  1813  	var buf bytes.Buffer
  1814  	fmt.Fprintf(&buf, "key-types=%s, lower=%q, upper=%q",
  1815  		o.KeyTypes, o.LowerBound, o.UpperBound)
  1816  	if o.TableFilter != nil {
  1817  		fmt.Fprintf(&buf, ", table-filter")
  1818  	}
  1819  	if o.OnlyReadGuaranteedDurable {
  1820  		fmt.Fprintf(&buf, ", only-durable")
  1821  	}
  1822  	if o.UseL6Filters {
  1823  		fmt.Fprintf(&buf, ", use-L6-filters")
  1824  	}
  1825  	for i, pkf := range o.PointKeyFilters {
  1826  		fmt.Fprintf(&buf, ", point-key-filter[%d]=%q", i, pkf.Name())
  1827  	}
  1828  	for i, rkf := range o.RangeKeyFilters {
  1829  		fmt.Fprintf(&buf, ", range-key-filter[%d]=%q", i, rkf.Name())
  1830  	}
  1831  	return buf.String()
  1832  }
  1833  
  1834  func newTestkeysDatabase(t *testing.T, ks testkeys.Keyspace, rng *rand.Rand) *DB {
  1835  	dbOpts := &Options{
  1836  		Comparer:           testkeys.Comparer,
  1837  		FS:                 vfs.NewMem(),
  1838  		FormatMajorVersion: FormatRangeKeys,
  1839  	}
  1840  	d, err := Open("", dbOpts)
  1841  	require.NoError(t, err)
  1842  
  1843  	// Randomize the order in which we write keys.
  1844  	order := rng.Perm(ks.Count())
  1845  	b := d.NewBatch()
  1846  	keyBuf := make([]byte, ks.MaxLen()+testkeys.MaxSuffixLen)
  1847  	keyBuf2 := make([]byte, ks.MaxLen()+testkeys.MaxSuffixLen)
  1848  	for i := 0; i < len(order); i++ {
  1849  		const maxVersionsPerKey = 10
  1850  		keyIndex := order[i]
  1851  		for versions := rng.Intn(maxVersionsPerKey); versions > 0; versions-- {
  1852  			n := testkeys.WriteKeyAt(keyBuf, ks, keyIndex, rng.Intn(maxVersionsPerKey))
  1853  			b.Set(keyBuf[:n], keyBuf[:n], nil)
  1854  		}
  1855  
  1856  		// Sometimes add a range key too.
  1857  		if rng.Intn(100) == 1 {
  1858  			startIdx := rng.Intn(ks.Count())
  1859  			endIdx := rng.Intn(ks.Count())
  1860  			startLen := testkeys.WriteKey(keyBuf, ks, startIdx)
  1861  			endLen := testkeys.WriteKey(keyBuf2, ks, endIdx)
  1862  			suffixInt := rng.Intn(maxVersionsPerKey)
  1863  			require.NoError(t, b.RangeKeySet(
  1864  				keyBuf[:startLen],
  1865  				keyBuf2[:endLen],
  1866  				testkeys.Suffix(suffixInt),
  1867  				nil,
  1868  				nil))
  1869  		}
  1870  
  1871  		// Randomize the flush points.
  1872  		if !b.Empty() && rng.Intn(10) == 1 {
  1873  			require.NoError(t, b.Commit(nil))
  1874  			require.NoError(t, d.Flush())
  1875  			b = d.NewBatch()
  1876  		}
  1877  	}
  1878  	if !b.Empty() {
  1879  		require.NoError(t, b.Commit(nil))
  1880  	}
  1881  	return d
  1882  }
  1883  
  1884  func newPointTestkeysDatabase(t *testing.T, ks testkeys.Keyspace) *DB {
  1885  	dbOpts := &Options{
  1886  		Comparer:           testkeys.Comparer,
  1887  		FS:                 vfs.NewMem(),
  1888  		FormatMajorVersion: FormatRangeKeys,
  1889  	}
  1890  	d, err := Open("", dbOpts)
  1891  	require.NoError(t, err)
  1892  
  1893  	b := d.NewBatch()
  1894  	keyBuf := make([]byte, ks.MaxLen()+testkeys.MaxSuffixLen)
  1895  	for i := 0; i < ks.Count(); i++ {
  1896  		n := testkeys.WriteKeyAt(keyBuf, ks, i, i)
  1897  		b.Set(keyBuf[:n], keyBuf[:n], nil)
  1898  	}
  1899  	require.NoError(t, b.Commit(nil))
  1900  	return d
  1901  }
  1902  
  1903  func BenchmarkIteratorSeekGE(b *testing.B) {
  1904  	m, keys := buildMemTable(b)
  1905  	iter := &Iterator{
  1906  		comparer: *DefaultComparer,
  1907  		iter:     m.newIter(nil),
  1908  	}
  1909  	rng := rand.New(rand.NewSource(uint64(time.Now().UnixNano())))
  1910  
  1911  	b.ResetTimer()
  1912  	for i := 0; i < b.N; i++ {
  1913  		key := keys[rng.Intn(len(keys))]
  1914  		iter.SeekGE(key)
  1915  	}
  1916  }
  1917  
  1918  func BenchmarkIteratorNext(b *testing.B) {
  1919  	m, _ := buildMemTable(b)
  1920  	iter := &Iterator{
  1921  		comparer: *DefaultComparer,
  1922  		iter:     m.newIter(nil),
  1923  	}
  1924  
  1925  	b.ResetTimer()
  1926  	for i := 0; i < b.N; i++ {
  1927  		if !iter.Valid() {
  1928  			iter.First()
  1929  		}
  1930  		iter.Next()
  1931  	}
  1932  }
  1933  
  1934  func BenchmarkIteratorPrev(b *testing.B) {
  1935  	m, _ := buildMemTable(b)
  1936  	iter := &Iterator{
  1937  		comparer: *DefaultComparer,
  1938  		iter:     m.newIter(nil),
  1939  	}
  1940  
  1941  	b.ResetTimer()
  1942  	for i := 0; i < b.N; i++ {
  1943  		if !iter.Valid() {
  1944  			iter.Last()
  1945  		}
  1946  		iter.Prev()
  1947  	}
  1948  }
  1949  
  1950  // BenchmarkIteratorSeqSeekPrefixGENotFound exercises the case of SeekPrefixGE
  1951  // specifying monotonic keys all of which precede actual keys present in L6 of
  1952  // the DB. Moreover, with-tombstone=true exercises the sub-case where those
  1953  // actual keys are deleted using a range tombstone that has not physically
  1954  // deleted those keys due to the presence of a snapshot that needs to see
  1955  // those keys. This sub-case needs to be efficient in (a) avoiding iteration
  1956  // over all those deleted keys, including repeated iteration, (b) using the
  1957  // next optimization, since the seeks are monotonic.
  1958  func BenchmarkIteratorSeqSeekPrefixGENotFound(b *testing.B) {
  1959  	const blockSize = 32 << 10
  1960  	const restartInterval = 16
  1961  	const levelCount = 5
  1962  	const keyOffset = 100000
  1963  
  1964  	var readers [4][][]*sstable.Reader
  1965  	var levelSlices [4][]manifest.LevelSlice
  1966  	indexFunc := func(bloom bool, withTombstone bool) int {
  1967  		index := 0
  1968  		if bloom {
  1969  			index = 2
  1970  		}
  1971  		if withTombstone {
  1972  			index++
  1973  		}
  1974  		return index
  1975  	}
  1976  	for _, bloom := range []bool{false, true} {
  1977  		for _, withTombstone := range []bool{false, true} {
  1978  			index := indexFunc(bloom, withTombstone)
  1979  			levels := levelCount
  1980  			if withTombstone {
  1981  				levels = 1
  1982  			}
  1983  			readers[index], levelSlices[index], _ = buildLevelsForMergingIterSeqSeek(
  1984  				b, blockSize, restartInterval, levels, keyOffset, withTombstone, bloom)
  1985  
  1986  		}
  1987  	}
  1988  	// We will not be seeking to the keys that were written but instead to
  1989  	// keys before the written keys. This is to validate that the optimization
  1990  	// to use Next still functions when mergingIter checks for the prefix
  1991  	// match, and that mergingIter can avoid iterating over all the keys
  1992  	// deleted by a range tombstone when there is no possibility of matching
  1993  	// the prefix.
  1994  	var keys [][]byte
  1995  	for i := 0; i < keyOffset; i++ {
  1996  		keys = append(keys, []byte(fmt.Sprintf("%08d", i)))
  1997  	}
  1998  	for _, skip := range []int{1, 2, 4} {
  1999  		for _, bloom := range []bool{false, true} {
  2000  			for _, withTombstone := range []bool{false, true} {
  2001  				b.Run(fmt.Sprintf("skip=%d/bloom=%t/with-tombstone=%t", skip, bloom, withTombstone),
  2002  					func(b *testing.B) {
  2003  						index := indexFunc(bloom, withTombstone)
  2004  						readers := readers[index]
  2005  						levelSlices := levelSlices[index]
  2006  						m := buildMergingIter(readers, levelSlices)
  2007  						iter := Iterator{
  2008  							comparer: *testkeys.Comparer,
  2009  							merge:    DefaultMerger.Merge,
  2010  							iter:     m,
  2011  						}
  2012  						pos := 0
  2013  						b.ResetTimer()
  2014  						for i := 0; i < b.N; i++ {
  2015  							// When withTombstone=true, and prior to the
  2016  							// optimization to stop early due to a range
  2017  							// tombstone, the iteration would continue into the
  2018  							// next file, and not be able to use Next at the lower
  2019  							// level in the next SeekPrefixGE call. So we would
  2020  							// incur the cost of iterating over all the deleted
  2021  							// keys for every seek. Note that it is not possible
  2022  							// to do a noop optimization in Iterator for the
  2023  							// prefix case, unlike SeekGE/SeekLT, since we don't
  2024  							// know if the iterators inside mergingIter are all
  2025  							// appropriately positioned -- some may not be due to
  2026  							// bloom filters not matching.
  2027  							valid := iter.SeekPrefixGE(keys[pos])
  2028  							if valid {
  2029  								b.Fatalf("key should not be found")
  2030  							}
  2031  							pos += skip
  2032  							if pos >= keyOffset {
  2033  								pos = 0
  2034  							}
  2035  						}
  2036  						b.StopTimer()
  2037  						iter.Close()
  2038  					})
  2039  			}
  2040  		}
  2041  	}
  2042  	for _, r := range readers {
  2043  		for i := range r {
  2044  			for j := range r[i] {
  2045  				r[i][j].Close()
  2046  			}
  2047  		}
  2048  	}
  2049  }
  2050  
  2051  // BenchmarkIteratorSeqSeekGEWithBounds is analogous to
  2052  // BenchmarkMergingIterSeqSeekGEWithBounds, except for using an Iterator,
  2053  // which causes it to exercise the end-to-end code path.
  2054  func BenchmarkIteratorSeqSeekGEWithBounds(b *testing.B) {
  2055  	const blockSize = 32 << 10
  2056  	const restartInterval = 16
  2057  	const levelCount = 5
  2058  	readers, levelSlices, keys := buildLevelsForMergingIterSeqSeek(
  2059  		b, blockSize, restartInterval, levelCount, 0 /* keyOffset */, false, false)
  2060  	m := buildMergingIter(readers, levelSlices)
  2061  	iter := Iterator{
  2062  		comparer: *testkeys.Comparer,
  2063  		merge:    DefaultMerger.Merge,
  2064  		iter:     m,
  2065  	}
  2066  	keyCount := len(keys)
  2067  	b.ResetTimer()
  2068  	for i := 0; i < b.N; i++ {
  2069  		pos := i % (keyCount - 1)
  2070  		iter.SetBounds(keys[pos], keys[pos+1])
  2071  		// SeekGE will return keys[pos].
  2072  		valid := iter.SeekGE(keys[pos])
  2073  		for valid {
  2074  			valid = iter.Next()
  2075  		}
  2076  		if iter.Error() != nil {
  2077  			b.Fatalf(iter.Error().Error())
  2078  		}
  2079  	}
  2080  	iter.Close()
  2081  	for i := range readers {
  2082  		for j := range readers[i] {
  2083  			readers[i][j].Close()
  2084  		}
  2085  	}
  2086  }
  2087  
  2088  func BenchmarkIteratorSeekGENoop(b *testing.B) {
  2089  	const blockSize = 32 << 10
  2090  	const restartInterval = 16
  2091  	const levelCount = 5
  2092  	const keyOffset = 10000
  2093  	readers, levelSlices, _ := buildLevelsForMergingIterSeqSeek(
  2094  		b, blockSize, restartInterval, levelCount, keyOffset, false, false)
  2095  	var keys [][]byte
  2096  	for i := 0; i < keyOffset; i++ {
  2097  		keys = append(keys, []byte(fmt.Sprintf("%08d", i)))
  2098  	}
  2099  	for _, withLimit := range []bool{false, true} {
  2100  		b.Run(fmt.Sprintf("withLimit=%t", withLimit), func(b *testing.B) {
  2101  			m := buildMergingIter(readers, levelSlices)
  2102  			iter := Iterator{
  2103  				comparer: *testkeys.Comparer,
  2104  				merge:    DefaultMerger.Merge,
  2105  				iter:     m,
  2106  			}
  2107  			b.ResetTimer()
  2108  			for i := 0; i < b.N; i++ {
  2109  				pos := i % (len(keys) - 1)
  2110  				if withLimit {
  2111  					if iter.SeekGEWithLimit(keys[pos], keys[pos+1]) != IterAtLimit {
  2112  						b.Fatal("should be at limit")
  2113  					}
  2114  				} else {
  2115  					if !iter.SeekGE(keys[pos]) {
  2116  						b.Fatal("should be valid")
  2117  					}
  2118  				}
  2119  			}
  2120  			iter.Close()
  2121  		})
  2122  	}
  2123  	for i := range readers {
  2124  		for j := range readers[i] {
  2125  			readers[i][j].Close()
  2126  		}
  2127  	}
  2128  }
  2129  
  2130  func BenchmarkBlockPropertyFilter(b *testing.B) {
  2131  	rng := rand.New(rand.NewSource(uint64(time.Now().UnixNano())))
  2132  	for _, matchInterval := range []int{1, 10, 100, 1000} {
  2133  		b.Run(fmt.Sprintf("match-interval=%d", matchInterval), func(b *testing.B) {
  2134  			mem := vfs.NewMem()
  2135  			opts := &Options{
  2136  				FS:                 mem,
  2137  				FormatMajorVersion: FormatNewest,
  2138  				BlockPropertyCollectors: []func() BlockPropertyCollector{
  2139  					func() BlockPropertyCollector {
  2140  						return sstable.NewBlockIntervalCollector(
  2141  							"0", &testBlockIntervalCollector{numLength: 3}, nil, /* range key collector */
  2142  						)
  2143  					},
  2144  				},
  2145  			}
  2146  			d, err := Open("", opts)
  2147  			require.NoError(b, err)
  2148  			defer func() {
  2149  				require.NoError(b, d.Close())
  2150  			}()
  2151  			batch := d.NewBatch()
  2152  			const numKeys = 20 * 1000
  2153  			const valueSize = 1000
  2154  			for i := 0; i < numKeys; i++ {
  2155  				key := fmt.Sprintf("%06d%03d", i, i%matchInterval)
  2156  				value := randValue(valueSize, rng)
  2157  				require.NoError(b, batch.Set([]byte(key), value, nil))
  2158  			}
  2159  			require.NoError(b, batch.Commit(nil))
  2160  			require.NoError(b, d.Flush())
  2161  			require.NoError(b, d.Compact(nil, []byte{0xFF}, false))
  2162  
  2163  			for _, filter := range []bool{false, true} {
  2164  				b.Run(fmt.Sprintf("filter=%t", filter), func(b *testing.B) {
  2165  					var iterOpts IterOptions
  2166  					if filter {
  2167  						iterOpts.PointKeyFilters = []BlockPropertyFilter{
  2168  							sstable.NewBlockIntervalFilter("0",
  2169  								uint64(0), uint64(1)),
  2170  						}
  2171  					}
  2172  					iter := d.NewIter(&iterOpts)
  2173  					b.ResetTimer()
  2174  					for i := 0; i < b.N; i++ {
  2175  						valid := iter.First()
  2176  						for valid {
  2177  							valid = iter.Next()
  2178  						}
  2179  					}
  2180  					b.StopTimer()
  2181  					require.NoError(b, iter.Close())
  2182  				})
  2183  			}
  2184  		})
  2185  	}
  2186  }
  2187  
  2188  // BenchmarkIterator_RangeKeyMasking benchmarks a scan through a keyspace with
  2189  // 10,000 random suffixed point keys, and three range keys covering most of the
  2190  // keyspace. It varies the suffix of the range keys in subbenchmarks to exercise
  2191  // varying amounts of masking. This benchmark does configure a block-property
  2192  // filter, allowing for skipping blocks wholly contained within a range key and
  2193  // consisting of points all with a suffix lower than the range key's.
  2194  func BenchmarkIterator_RangeKeyMasking(b *testing.B) {
  2195  	const (
  2196  		prefixLen    = 20
  2197  		valueSize    = 1024
  2198  		batches      = 200
  2199  		keysPerBatch = 50
  2200  	)
  2201  	rng := rand.New(rand.NewSource(uint64(1658872515083979000)))
  2202  	keyBuf := make([]byte, prefixLen+testkeys.MaxSuffixLen)
  2203  	valBuf := make([]byte, valueSize)
  2204  
  2205  	mem := vfs.NewStrictMem()
  2206  	maxProcs := runtime.GOMAXPROCS(0)
  2207  	opts := &Options{
  2208  		FS:                       mem,
  2209  		Comparer:                 testkeys.Comparer,
  2210  		FormatMajorVersion:       FormatNewest,
  2211  		MaxConcurrentCompactions: func() int { return maxProcs/2 + 1 },
  2212  		BlockPropertyCollectors: []func() BlockPropertyCollector{
  2213  			blockprop.NewBlockPropertyCollector,
  2214  		},
  2215  	}
  2216  	d, err := Open("", opts)
  2217  	require.NoError(b, err)
  2218  
  2219  	for bi := 0; bi < batches; bi++ {
  2220  		batch := d.NewBatch()
  2221  		for k := 0; k < keysPerBatch; k++ {
  2222  			randStr(keyBuf[:prefixLen], rng)
  2223  			suffix := rng.Intn(100)
  2224  			suffixLen := testkeys.WriteSuffix(keyBuf[prefixLen:], suffix)
  2225  			randStr(valBuf[:], rng)
  2226  			require.NoError(b, batch.Set(keyBuf[:prefixLen+suffixLen], valBuf[:], nil))
  2227  		}
  2228  		require.NoError(b, batch.Commit(nil))
  2229  	}
  2230  
  2231  	// Wait for compactions to complete before starting benchmarks. We don't
  2232  	// want to benchmark while compactions are running.
  2233  	d.mu.Lock()
  2234  	for d.mu.compact.compactingCount > 0 {
  2235  		d.mu.compact.cond.Wait()
  2236  	}
  2237  	d.mu.Unlock()
  2238  	b.Log(d.Metrics().String())
  2239  	require.NoError(b, d.Close())
  2240  	// Set ignore syncs to true so that each subbenchmark may mutate state and
  2241  	// then revert back to the original state.
  2242  	mem.SetIgnoreSyncs(true)
  2243  
  2244  	// TODO(jackson): Benchmark lazy-combined iteration versus not.
  2245  	// TODO(jackson): Benchmark seeks.
  2246  	for _, rkSuffix := range []string{"@10", "@50", "@75", "@100"} {
  2247  		b.Run(fmt.Sprintf("range-keys-suffixes=%s", rkSuffix), func(b *testing.B) {
  2248  			d, err := Open("", opts)
  2249  			require.NoError(b, err)
  2250  			require.NoError(b, d.RangeKeySet([]byte("b"), []byte("e"), []byte(rkSuffix), nil, nil))
  2251  			require.NoError(b, d.RangeKeySet([]byte("f"), []byte("p"), []byte(rkSuffix), nil, nil))
  2252  			require.NoError(b, d.RangeKeySet([]byte("q"), []byte("z"), []byte(rkSuffix), nil, nil))
  2253  			require.NoError(b, d.Flush())
  2254  
  2255  			// Populate 3 range keys, covering most of the keyspace, at the
  2256  			// given suffix.
  2257  
  2258  			iterOpts := IterOptions{
  2259  				KeyTypes: IterKeyTypePointsAndRanges,
  2260  				RangeKeyMasking: RangeKeyMasking{
  2261  					Suffix: []byte("@100"),
  2262  					Filter: func() BlockPropertyFilterMask {
  2263  						return blockprop.NewMaskingFilter()
  2264  					},
  2265  				},
  2266  			}
  2267  			b.Run("forward", func(b *testing.B) {
  2268  				b.ResetTimer()
  2269  				for i := 0; i < b.N; i++ {
  2270  					iter := d.NewIter(&iterOpts)
  2271  					count := 0
  2272  					for valid := iter.First(); valid; valid = iter.Next() {
  2273  						if hasPoint, _ := iter.HasPointAndRange(); hasPoint {
  2274  							count++
  2275  						}
  2276  					}
  2277  					if err := iter.Close(); err != nil {
  2278  						b.Fatal(err)
  2279  					}
  2280  				}
  2281  			})
  2282  			b.Run("backward", func(b *testing.B) {
  2283  				b.ResetTimer()
  2284  				for i := 0; i < b.N; i++ {
  2285  					iter := d.NewIter(&iterOpts)
  2286  					count := 0
  2287  					for valid := iter.Last(); valid; valid = iter.Prev() {
  2288  						if hasPoint, _ := iter.HasPointAndRange(); hasPoint {
  2289  							count++
  2290  						}
  2291  					}
  2292  					if err := iter.Close(); err != nil {
  2293  						b.Fatal(err)
  2294  					}
  2295  				}
  2296  			})
  2297  
  2298  			// Reset the benchmark state at the end of each run to remove the
  2299  			// range keys we wrote.
  2300  			b.StopTimer()
  2301  			require.NoError(b, d.Close())
  2302  			mem.ResetToSyncedState()
  2303  		})
  2304  	}
  2305  
  2306  }
  2307  
  2308  func BenchmarkIteratorScan(b *testing.B) {
  2309  	const maxPrefixLen = 8
  2310  	keyBuf := make([]byte, maxPrefixLen+testkeys.MaxSuffixLen)
  2311  	rng := rand.New(rand.NewSource(uint64(time.Now().UnixNano())))
  2312  
  2313  	for _, keyCount := range []int{100, 1000, 10000} {
  2314  		for _, readAmp := range []int{1, 3, 7, 10} {
  2315  			func() {
  2316  				opts := &Options{
  2317  					FS:                 vfs.NewMem(),
  2318  					FormatMajorVersion: FormatNewest,
  2319  				}
  2320  				opts.DisableAutomaticCompactions = true
  2321  				d, err := Open("", opts)
  2322  				require.NoError(b, err)
  2323  				defer func() { require.NoError(b, d.Close()) }()
  2324  
  2325  				// Take the very large keyspace consisting of alphabetic
  2326  				// characters of lengths up to `maxPrefixLen` and reduce it down
  2327  				// to `keyCount` keys by picking every 1 key every `keyCount` keys.
  2328  				keys := testkeys.Alpha(maxPrefixLen)
  2329  				keys = keys.EveryN(keys.Count() / keyCount)
  2330  				if keys.Count() < keyCount {
  2331  					b.Fatalf("expected %d keys, found %d", keyCount, keys.Count())
  2332  				}
  2333  
  2334  				// Portion the keys into `readAmp` overlapping key sets.
  2335  				for _, ks := range testkeys.Divvy(keys, readAmp) {
  2336  					batch := d.NewBatch()
  2337  					for i := 0; i < ks.Count(); i++ {
  2338  						n := testkeys.WriteKeyAt(keyBuf[:], ks, i, int(rng.Uint64n(100)))
  2339  						batch.Set(keyBuf[:n], keyBuf[:n], nil)
  2340  					}
  2341  					require.NoError(b, batch.Commit(nil))
  2342  					require.NoError(b, d.Flush())
  2343  				}
  2344  				// Each level is a sublevel.
  2345  				m := d.Metrics()
  2346  				require.Equal(b, readAmp, m.ReadAmp())
  2347  
  2348  				for _, keyTypes := range []IterKeyType{IterKeyTypePointsOnly, IterKeyTypePointsAndRanges} {
  2349  					iterOpts := IterOptions{KeyTypes: keyTypes}
  2350  					b.Run(fmt.Sprintf("keys=%d,r-amp=%d,key-types=%s", keyCount, readAmp, keyTypes), func(b *testing.B) {
  2351  						for i := 0; i < b.N; i++ {
  2352  							b.StartTimer()
  2353  							iter := d.NewIter(&iterOpts)
  2354  							valid := iter.First()
  2355  							for valid {
  2356  								valid = iter.Next()
  2357  							}
  2358  							b.StopTimer()
  2359  							require.NoError(b, iter.Close())
  2360  						}
  2361  					})
  2362  				}
  2363  			}()
  2364  		}
  2365  	}
  2366  }
  2367  
  2368  func BenchmarkCombinedIteratorSeek(b *testing.B) {
  2369  	for _, withRangeKey := range []bool{false, true} {
  2370  		b.Run(fmt.Sprintf("range-key=%t", withRangeKey), func(b *testing.B) {
  2371  			rng := rand.New(rand.NewSource(uint64(1658872515083979000)))
  2372  			ks := testkeys.Alpha(1)
  2373  			opts := &Options{
  2374  				FS:                 vfs.NewMem(),
  2375  				Comparer:           testkeys.Comparer,
  2376  				FormatMajorVersion: FormatNewest,
  2377  			}
  2378  			d, err := Open("", opts)
  2379  			require.NoError(b, err)
  2380  			defer func() { require.NoError(b, d.Close()) }()
  2381  
  2382  			keys := make([][]byte, ks.Count())
  2383  			for i := 0; i < ks.Count(); i++ {
  2384  				keys[i] = testkeys.Key(ks, i)
  2385  				var val [40]byte
  2386  				rng.Read(val[:])
  2387  				require.NoError(b, d.Set(keys[i], val[:], nil))
  2388  			}
  2389  			if withRangeKey {
  2390  				require.NoError(b, d.RangeKeySet([]byte("a"), []byte{'z', 0x00}, []byte("@5"), nil, nil))
  2391  			}
  2392  
  2393  			batch := d.NewIndexedBatch()
  2394  			defer batch.Close()
  2395  
  2396  			for _, useBatch := range []bool{false, true} {
  2397  				b.Run(fmt.Sprintf("batch=%t", useBatch), func(b *testing.B) {
  2398  					for i := 0; i < b.N; i++ {
  2399  						iterOpts := IterOptions{KeyTypes: IterKeyTypePointsAndRanges}
  2400  						var it *Iterator
  2401  						if useBatch {
  2402  							it = batch.NewIter(&iterOpts)
  2403  						} else {
  2404  							it = d.NewIter(&iterOpts)
  2405  						}
  2406  						for j := 0; j < len(keys); j++ {
  2407  							if !it.SeekGE(keys[j]) {
  2408  								b.Errorf("key %q missing", keys[j])
  2409  							}
  2410  						}
  2411  						require.NoError(b, it.Close())
  2412  					}
  2413  				})
  2414  			}
  2415  		})
  2416  	}
  2417  }
  2418  
  2419  // BenchmarkCombinedIteratorSeek_Bounded benchmarks a bounded iterator that
  2420  // performs repeated seeks over 5% of the middle of a keyspace covered by a
  2421  // range key that's fragmented across hundreds of files. The iterator bounds
  2422  // should prevent defragmenting beyond the iterator's bounds.
  2423  func BenchmarkCombinedIteratorSeek_Bounded(b *testing.B) {
  2424  	d, keys := buildFragmentedRangeKey(b, uint64(1658872515083979000))
  2425  
  2426  	var lower = len(keys) / 2
  2427  	var upper = len(keys)/2 + len(keys)/20 // 5%
  2428  	iterOpts := IterOptions{
  2429  		KeyTypes:   IterKeyTypePointsAndRanges,
  2430  		LowerBound: keys[lower],
  2431  		UpperBound: keys[upper],
  2432  	}
  2433  	b.ResetTimer()
  2434  	for i := 0; i < b.N; i++ {
  2435  		it := d.NewIter(&iterOpts)
  2436  		for j := lower; j < upper; j++ {
  2437  			if !it.SeekGE(keys[j]) {
  2438  				b.Errorf("key %q missing", keys[j])
  2439  			}
  2440  		}
  2441  		require.NoError(b, it.Close())
  2442  	}
  2443  }
  2444  
  2445  // BenchmarkCombinedIteratorSeekPrefix benchmarks an iterator that
  2446  // performs repeated prefix seeks over 5% of the middle of a keyspace covered by a
  2447  // range key that's fragmented across hundreds of files. The seek prefix should
  2448  // avoid defragmenting beyond the seek prefixes.
  2449  func BenchmarkCombinedIteratorSeekPrefix(b *testing.B) {
  2450  	d, keys := buildFragmentedRangeKey(b, uint64(1658872515083979000))
  2451  
  2452  	var lower = len(keys) / 2
  2453  	var upper = len(keys)/2 + len(keys)/20 // 5%
  2454  	iterOpts := IterOptions{
  2455  		KeyTypes: IterKeyTypePointsAndRanges,
  2456  	}
  2457  	b.ResetTimer()
  2458  	for i := 0; i < b.N; i++ {
  2459  		it := d.NewIter(&iterOpts)
  2460  		for j := lower; j < upper; j++ {
  2461  			if !it.SeekPrefixGE(keys[j]) {
  2462  				b.Errorf("key %q missing", keys[j])
  2463  			}
  2464  		}
  2465  		require.NoError(b, it.Close())
  2466  	}
  2467  }
  2468  
  2469  func buildFragmentedRangeKey(b testing.TB, seed uint64) (d *DB, keys [][]byte) {
  2470  	rng := rand.New(rand.NewSource(seed))
  2471  	ks := testkeys.Alpha(2)
  2472  	opts := &Options{
  2473  		FS:                        vfs.NewMem(),
  2474  		Comparer:                  testkeys.Comparer,
  2475  		FormatMajorVersion:        FormatNewest,
  2476  		L0CompactionFileThreshold: 1,
  2477  	}
  2478  	opts.EnsureDefaults()
  2479  	for l := 0; l < len(opts.Levels); l++ {
  2480  		opts.Levels[l].TargetFileSize = 1
  2481  	}
  2482  	var err error
  2483  	d, err = Open("", opts)
  2484  	require.NoError(b, err)
  2485  
  2486  	keys = make([][]byte, ks.Count())
  2487  	for i := 0; i < ks.Count(); i++ {
  2488  		keys[i] = testkeys.Key(ks, i)
  2489  	}
  2490  	for i := 0; i < len(keys); i++ {
  2491  		var val [40]byte
  2492  		rng.Read(val[:])
  2493  		require.NoError(b, d.Set(keys[i], val[:], nil))
  2494  		if i < len(keys)-1 {
  2495  			require.NoError(b, d.RangeKeySet(keys[i], keys[i+1], []byte("@5"), nil, nil))
  2496  		}
  2497  		require.NoError(b, d.Flush())
  2498  	}
  2499  
  2500  	d.mu.Lock()
  2501  	for d.mu.compact.compactingCount > 0 {
  2502  		d.mu.compact.cond.Wait()
  2503  	}
  2504  	v := d.mu.versions.currentVersion()
  2505  	d.mu.Unlock()
  2506  	require.GreaterOrEqualf(b, v.Levels[numLevels-1].Len(),
  2507  		700, "expect many (≥700) L6 files but found %d", v.Levels[numLevels-1].Len())
  2508  	return d, keys
  2509  }