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

     1  // Copyright 2012 The LevelDB-Go and Pebble 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  	"encoding/binary"
    10  	"fmt"
    11  	"io"
    12  	"math"
    13  	"math/rand"
    14  	"strconv"
    15  	"strings"
    16  	"testing"
    17  	"time"
    18  
    19  	"github.com/cockroachdb/errors"
    20  	"github.com/stretchr/testify/require"
    21  	"github.com/zuoyebang/bitalostable/internal/base"
    22  	"github.com/zuoyebang/bitalostable/internal/batchskl"
    23  	"github.com/zuoyebang/bitalostable/internal/datadriven"
    24  	"github.com/zuoyebang/bitalostable/internal/keyspan"
    25  	"github.com/zuoyebang/bitalostable/internal/testkeys"
    26  	"github.com/zuoyebang/bitalostable/vfs"
    27  )
    28  
    29  func TestBatch(t *testing.T) {
    30  	type testCase struct {
    31  		kind       InternalKeyKind
    32  		key, value string
    33  	}
    34  
    35  	verifyTestCases := func(b *Batch, testCases []testCase) {
    36  		r := b.Reader()
    37  
    38  		for _, tc := range testCases {
    39  			kind, k, v, ok := r.Next()
    40  			if !ok {
    41  				t.Fatalf("next returned !ok: test case = %v", tc)
    42  			}
    43  			key, value := string(k), string(v)
    44  			if kind != tc.kind || key != tc.key || value != tc.value {
    45  				t.Errorf("got (%d, %q, %q), want (%d, %q, %q)",
    46  					kind, key, value, tc.kind, tc.key, tc.value)
    47  			}
    48  		}
    49  		if len(r) != 0 {
    50  			t.Errorf("reader was not exhausted: remaining bytes = %q", r)
    51  		}
    52  	}
    53  
    54  	// RangeKeySet and RangeKeyUnset are untested here because they don't expose
    55  	// deferred variants. This is a consequence of these keys' more complex
    56  	// value encodings.
    57  	testCases := []testCase{
    58  		{InternalKeyKindSet, "roses", "red"},
    59  		{InternalKeyKindSet, "violets", "blue"},
    60  		{InternalKeyKindDelete, "roses", ""},
    61  		{InternalKeyKindSingleDelete, "roses", ""},
    62  		{InternalKeyKindSet, "", ""},
    63  		{InternalKeyKindSet, "", "non-empty"},
    64  		{InternalKeyKindDelete, "", ""},
    65  		{InternalKeyKindSingleDelete, "", ""},
    66  		{InternalKeyKindSet, "grass", "green"},
    67  		{InternalKeyKindSet, "grass", "greener"},
    68  		{InternalKeyKindSet, "eleventy", strings.Repeat("!!11!", 100)},
    69  		{InternalKeyKindDelete, "nosuchkey", ""},
    70  		{InternalKeyKindSingleDelete, "nosuchkey", ""},
    71  		{InternalKeyKindSet, "binarydata", "\x00"},
    72  		{InternalKeyKindSet, "binarydata", "\xff"},
    73  		{InternalKeyKindMerge, "merge", "mergedata"},
    74  		{InternalKeyKindMerge, "merge", ""},
    75  		{InternalKeyKindMerge, "", ""},
    76  		{InternalKeyKindRangeDelete, "a", "b"},
    77  		{InternalKeyKindRangeDelete, "", ""},
    78  		{InternalKeyKindLogData, "logdata", ""},
    79  		{InternalKeyKindLogData, "", ""},
    80  		{InternalKeyKindRangeKeyDelete, "grass", "green"},
    81  		{InternalKeyKindRangeKeyDelete, "", ""},
    82  	}
    83  	var b Batch
    84  	for _, tc := range testCases {
    85  		switch tc.kind {
    86  		case InternalKeyKindSet:
    87  			_ = b.Set([]byte(tc.key), []byte(tc.value), nil)
    88  		case InternalKeyKindMerge:
    89  			_ = b.Merge([]byte(tc.key), []byte(tc.value), nil)
    90  		case InternalKeyKindDelete:
    91  			_ = b.Delete([]byte(tc.key), nil)
    92  		case InternalKeyKindSingleDelete:
    93  			_ = b.SingleDelete([]byte(tc.key), nil)
    94  		case InternalKeyKindRangeDelete:
    95  			_ = b.DeleteRange([]byte(tc.key), []byte(tc.value), nil)
    96  		case InternalKeyKindLogData:
    97  			_ = b.LogData([]byte(tc.key), nil)
    98  		case InternalKeyKindRangeKeyDelete:
    99  			_ = b.RangeKeyDelete([]byte(tc.key), []byte(tc.value), nil)
   100  		}
   101  	}
   102  	verifyTestCases(&b, testCases)
   103  
   104  	b.Reset()
   105  	// Run the same operations, this time using the Deferred variants of each
   106  	// operation (eg. SetDeferred).
   107  	for _, tc := range testCases {
   108  		key := []byte(tc.key)
   109  		value := []byte(tc.value)
   110  		switch tc.kind {
   111  		case InternalKeyKindSet:
   112  			d := b.SetDeferred(len(key), len(value))
   113  			copy(d.Key, key)
   114  			copy(d.Value, value)
   115  			d.Finish()
   116  		case InternalKeyKindMerge:
   117  			d := b.MergeDeferred(len(key), len(value))
   118  			copy(d.Key, key)
   119  			copy(d.Value, value)
   120  			d.Finish()
   121  		case InternalKeyKindDelete:
   122  			d := b.DeleteDeferred(len(key))
   123  			copy(d.Key, key)
   124  			copy(d.Value, value)
   125  			d.Finish()
   126  		case InternalKeyKindSingleDelete:
   127  			d := b.SingleDeleteDeferred(len(key))
   128  			copy(d.Key, key)
   129  			copy(d.Value, value)
   130  			d.Finish()
   131  		case InternalKeyKindRangeDelete:
   132  			d := b.DeleteRangeDeferred(len(key), len(value))
   133  			copy(d.Key, key)
   134  			copy(d.Value, value)
   135  			d.Finish()
   136  		case InternalKeyKindLogData:
   137  			_ = b.LogData([]byte(tc.key), nil)
   138  		case InternalKeyKindRangeKeyDelete:
   139  			d := b.RangeKeyDeleteDeferred(len(key), len(value))
   140  			copy(d.Key, key)
   141  			copy(d.Value, value)
   142  			d.Finish()
   143  		}
   144  	}
   145  	verifyTestCases(&b, testCases)
   146  }
   147  
   148  func TestBatchLen(t *testing.T) {
   149  	var b Batch
   150  
   151  	requireLenAndReprEq := func(size int) {
   152  		require.Equal(t, size, b.Len())
   153  		require.Equal(t, size, len(b.Repr()))
   154  	}
   155  
   156  	requireLenAndReprEq(batchHeaderLen)
   157  
   158  	key := "test-key"
   159  	value := "test-value"
   160  
   161  	err := b.Set([]byte(key), []byte(value), nil)
   162  	require.NoError(t, err)
   163  
   164  	requireLenAndReprEq(33)
   165  
   166  	err = b.Delete([]byte(key), nil)
   167  	require.NoError(t, err)
   168  
   169  	requireLenAndReprEq(43)
   170  }
   171  
   172  func TestBatchEmpty(t *testing.T) {
   173  	var b Batch
   174  	require.True(t, b.Empty())
   175  
   176  	ops := []func(*Batch) error{
   177  		func(b *Batch) error { return b.Set(nil, nil, nil) },
   178  		func(b *Batch) error { return b.Merge(nil, nil, nil) },
   179  		func(b *Batch) error { return b.Delete(nil, nil) },
   180  		func(b *Batch) error { return b.DeleteRange(nil, nil, nil) },
   181  		func(b *Batch) error { return b.LogData(nil, nil) },
   182  		func(b *Batch) error { return b.RangeKeySet(nil, nil, nil, nil, nil) },
   183  		func(b *Batch) error { return b.RangeKeyUnset(nil, nil, nil, nil) },
   184  		func(b *Batch) error { return b.RangeKeyDelete(nil, nil, nil) },
   185  	}
   186  
   187  	for _, op := range ops {
   188  		require.NoError(t, op(&b))
   189  		require.False(t, b.Empty())
   190  		b.Reset()
   191  		require.True(t, b.Empty())
   192  		// Reset may choose to reuse b.data, so clear it to the zero value in
   193  		// order to test the lazy initialization of b.data.
   194  		b = Batch{}
   195  	}
   196  
   197  	_ = b.Reader()
   198  	require.True(t, b.Empty())
   199  	b.Reset()
   200  	require.True(t, b.Empty())
   201  	b = Batch{}
   202  
   203  	require.Equal(t, uint64(0), b.SeqNum())
   204  	require.True(t, b.Empty())
   205  	b.Reset()
   206  	require.True(t, b.Empty())
   207  	b = Batch{}
   208  
   209  	d, err := Open("", &Options{
   210  		FS: vfs.NewMem(),
   211  	})
   212  	require.NoError(t, err)
   213  	defer d.Close()
   214  	ib := newIndexedBatch(d, DefaultComparer)
   215  	iter := ib.NewIter(nil)
   216  	require.False(t, iter.First())
   217  	iter2, err := iter.Clone(CloneOptions{})
   218  	require.NoError(t, err)
   219  	require.NoError(t, iter.Close())
   220  	_, err = iter.Clone(CloneOptions{})
   221  	require.True(t, err != nil)
   222  	require.False(t, iter2.First())
   223  	require.NoError(t, iter2.Close())
   224  }
   225  
   226  func TestBatchReset(t *testing.T) {
   227  	db, err := Open("", &Options{
   228  		FS: vfs.NewMem(),
   229  	})
   230  	require.NoError(t, err)
   231  	defer db.Close()
   232  	key := "test-key"
   233  	value := "test-value"
   234  	b := db.NewBatch()
   235  	require.NoError(t, b.Set([]byte(key), []byte(value), nil))
   236  	dd := b.DeleteRangeDeferred(len(key), len(value))
   237  	copy(dd.Key, key)
   238  	copy(dd.Value, value)
   239  	dd.Finish()
   240  
   241  	require.NoError(t, b.RangeKeySet([]byte(key), []byte(value), []byte(value), []byte(value), nil))
   242  
   243  	b.setSeqNum(100)
   244  	b.applied = 1
   245  	b.commitErr = errors.New("test-error")
   246  	b.commit.Add(1)
   247  	require.Equal(t, uint32(3), b.Count())
   248  	require.Equal(t, uint64(1), b.countRangeDels)
   249  	require.Equal(t, uint64(1), b.countRangeKeys)
   250  	require.True(t, len(b.data) > 0)
   251  	require.True(t, b.SeqNum() > 0)
   252  	require.True(t, b.memTableSize > 0)
   253  	require.NotEqual(t, b.deferredOp, DeferredBatchOp{})
   254  
   255  	b.Reset()
   256  	require.Equal(t, db, b.db)
   257  	require.Equal(t, uint32(0), b.applied)
   258  	require.Nil(t, b.commitErr)
   259  	require.Equal(t, uint32(0), b.Count())
   260  	require.Equal(t, uint64(0), b.countRangeDels)
   261  	require.Equal(t, uint64(0), b.countRangeKeys)
   262  	require.Equal(t, batchHeaderLen, len(b.data))
   263  	require.Equal(t, uint64(0), b.SeqNum())
   264  	require.Equal(t, uint64(0), b.memTableSize)
   265  	require.Equal(t, b.deferredOp, DeferredBatchOp{})
   266  
   267  	var expected Batch
   268  	expected.SetRepr(b.data)
   269  	expected.db = db
   270  	require.Equal(t, &expected, b)
   271  
   272  	// Reset batch can be used to write and commit a new record.
   273  	b.Set([]byte(key), []byte(value), nil)
   274  	require.NoError(t, db.Apply(b, nil))
   275  	v, closer, err := db.Get([]byte(key))
   276  	require.NoError(t, err)
   277  	defer closer.Close()
   278  	require.Equal(t, v, []byte(value))
   279  }
   280  
   281  func TestIndexedBatchReset(t *testing.T) {
   282  	indexCount := func(sl *batchskl.Skiplist) int {
   283  		count := 0
   284  		iter := sl.NewIter(nil, nil)
   285  		defer iter.Close()
   286  		for iter.First(); iter.Valid(); iter.Next() {
   287  			count++
   288  		}
   289  		return count
   290  	}
   291  	db, err := Open("", &Options{
   292  		FS: vfs.NewMem(),
   293  	})
   294  	require.NoError(t, err)
   295  	defer db.Close()
   296  	b := newIndexedBatch(db, DefaultComparer)
   297  	start := "start-key"
   298  	end := "end-key"
   299  	key := "test-key"
   300  	value := "test-value"
   301  	b.DeleteRange([]byte(start), []byte(end), nil)
   302  	b.Set([]byte(key), []byte(value), nil)
   303  	require.NoError(t, b.
   304  		RangeKeySet([]byte(start), []byte(end), []byte("suffix"), []byte(value), nil))
   305  	require.NotNil(t, b.rangeKeyIndex)
   306  	require.NotNil(t, b.rangeDelIndex)
   307  	require.NotNil(t, b.index)
   308  	require.Equal(t, 1, indexCount(b.index))
   309  
   310  	b.Reset()
   311  	require.NotNil(t, b.cmp)
   312  	require.NotNil(t, b.formatKey)
   313  	require.NotNil(t, b.abbreviatedKey)
   314  	require.NotNil(t, b.index)
   315  	require.Nil(t, b.rangeDelIndex)
   316  	require.Nil(t, b.rangeKeyIndex)
   317  
   318  	count := func(ib *Batch) int {
   319  		iter := ib.NewIter(nil)
   320  		defer iter.Close()
   321  		iter2, err := iter.Clone(CloneOptions{})
   322  		require.NoError(t, err)
   323  		defer iter2.Close()
   324  		var count [2]int
   325  		for i, it := range []*Iterator{iter, iter2} {
   326  			for it.First(); it.Valid(); it.Next() {
   327  				count[i]++
   328  			}
   329  		}
   330  		require.Equal(t, count[0], count[1])
   331  		return count[0]
   332  	}
   333  	contains := func(ib *Batch, key, value string) bool {
   334  		iter := ib.NewIter(nil)
   335  		defer iter.Close()
   336  		iter2, err := iter.Clone(CloneOptions{})
   337  		require.NoError(t, err)
   338  		defer iter2.Close()
   339  		var found [2]bool
   340  		for i, it := range []*Iterator{iter, iter2} {
   341  			for it.First(); it.Valid(); it.Next() {
   342  				if string(it.Key()) == key &&
   343  					string(it.Value()) == value {
   344  					found[i] = true
   345  				}
   346  			}
   347  		}
   348  		require.Equal(t, found[0], found[1])
   349  		return found[0]
   350  	}
   351  	// Set a key and check whether the key-value pair is visible.
   352  	b.Set([]byte(key), []byte(value), nil)
   353  	require.Equal(t, 1, indexCount(b.index))
   354  	require.Equal(t, 1, count(b))
   355  	require.True(t, contains(b, key, value))
   356  
   357  	// Use range delete to delete the above inserted key-value pair.
   358  	b.DeleteRange([]byte(key), []byte(value), nil)
   359  	require.NotNil(t, b.rangeDelIndex)
   360  	require.Equal(t, 1, indexCount(b.rangeDelIndex))
   361  	require.Equal(t, 0, count(b))
   362  	require.False(t, contains(b, key, value))
   363  }
   364  
   365  // TestIndexedBatchMutation tests mutating an indexed batch with an open
   366  // iterator.
   367  func TestIndexedBatchMutation(t *testing.T) {
   368  	opts := &Options{
   369  		Comparer:           testkeys.Comparer,
   370  		FS:                 vfs.NewMem(),
   371  		FormatMajorVersion: FormatNewest,
   372  	}
   373  	d, err := Open("", opts)
   374  	require.NoError(t, err)
   375  	defer func() { d.Close() }()
   376  
   377  	b := newIndexedBatch(d, DefaultComparer)
   378  	iters := map[string]*Iterator{}
   379  	defer func() {
   380  		for _, iter := range iters {
   381  			require.NoError(t, iter.Close())
   382  		}
   383  	}()
   384  
   385  	datadriven.RunTest(t, "testdata/indexed_batch_mutation", func(td *datadriven.TestData) string {
   386  		switch td.Cmd {
   387  		case "batch":
   388  			writeBatch := newBatch(d)
   389  			if err := runBatchDefineCmd(td, writeBatch); err != nil {
   390  				return err.Error()
   391  			}
   392  			if err := writeBatch.Commit(nil); err != nil {
   393  				return err.Error()
   394  			}
   395  			return ""
   396  		case "new-batch-iter":
   397  			name := td.CmdArgs[0].String()
   398  			iters[name] = b.NewIter(&IterOptions{
   399  				KeyTypes: IterKeyTypePointsAndRanges,
   400  			})
   401  			return ""
   402  		case "new-db-iter":
   403  			name := td.CmdArgs[0].String()
   404  			iters[name] = d.NewIter(&IterOptions{
   405  				KeyTypes: IterKeyTypePointsAndRanges,
   406  			})
   407  			return ""
   408  		case "new-batch":
   409  			if b != nil {
   410  				require.NoError(t, b.Close())
   411  			}
   412  			b = newIndexedBatch(d, opts.Comparer)
   413  			if err := runBatchDefineCmd(td, b); err != nil {
   414  				return err.Error()
   415  			}
   416  			return ""
   417  		case "flush":
   418  			require.NoError(t, d.Flush())
   419  			return ""
   420  		case "iter":
   421  			var iter string
   422  			td.ScanArgs(t, "iter", &iter)
   423  			return runIterCmd(td, iters[iter], false /* closeIter */)
   424  		case "mutate":
   425  			mut := newBatch(d)
   426  			if err := runBatchDefineCmd(td, mut); err != nil {
   427  				return err.Error()
   428  			}
   429  			if err := b.Apply(mut, nil); err != nil {
   430  				return err.Error()
   431  			}
   432  			return ""
   433  		case "clone":
   434  			var from, to string
   435  			var refreshBatchView bool
   436  			td.ScanArgs(t, "from", &from)
   437  			td.ScanArgs(t, "to", &to)
   438  			td.ScanArgs(t, "refresh-batch", &refreshBatchView)
   439  			var err error
   440  			iters[to], err = iters[from].Clone(CloneOptions{RefreshBatchView: refreshBatchView})
   441  			if err != nil {
   442  				return err.Error()
   443  			}
   444  			return ""
   445  		case "reset":
   446  			for key, iter := range iters {
   447  				if err := iter.Close(); err != nil {
   448  					return err.Error()
   449  				}
   450  				delete(iters, key)
   451  			}
   452  			if d != nil {
   453  				if err := d.Close(); err != nil {
   454  					return err.Error()
   455  				}
   456  			}
   457  			opts.FS = vfs.NewMem()
   458  			d, err = Open("", opts)
   459  			require.NoError(t, err)
   460  			return ""
   461  		default:
   462  			return fmt.Sprintf("unrecognized command %q", td.Cmd)
   463  		}
   464  	})
   465  }
   466  
   467  func TestIndexedBatch_GlobalVisibility(t *testing.T) {
   468  	opts := &Options{
   469  		FS:                 vfs.NewMem(),
   470  		FormatMajorVersion: FormatNewest,
   471  		Comparer:           testkeys.Comparer,
   472  	}
   473  	d, err := Open("", opts)
   474  	require.NoError(t, err)
   475  	defer d.Close()
   476  
   477  	require.NoError(t, d.Set([]byte("foo"), []byte("foo"), nil))
   478  
   479  	// Create an iterator over an empty indexed batch.
   480  	b := newIndexedBatch(d, DefaultComparer)
   481  	iterOpts := IterOptions{KeyTypes: IterKeyTypePointsAndRanges}
   482  	iter := b.NewIter(&iterOpts)
   483  	defer iter.Close()
   484  
   485  	// Mutate the database's committed state.
   486  	mut := newBatch(d)
   487  	require.NoError(t, mut.Set([]byte("bar"), []byte("bar"), nil))
   488  	require.NoError(t, mut.DeleteRange([]byte("e"), []byte("g"), nil))
   489  	require.NoError(t, mut.RangeKeySet([]byte("a"), []byte("c"), []byte("@1"), []byte("v"), nil))
   490  	require.NoError(t, mut.Commit(nil))
   491  
   492  	scanIter := func() string {
   493  		var buf bytes.Buffer
   494  		for valid := iter.First(); valid; valid = iter.Next() {
   495  			fmt.Fprintf(&buf, "%s: (", iter.Key())
   496  			hasPoint, hasRange := iter.HasPointAndRange()
   497  			if hasPoint {
   498  				fmt.Fprintf(&buf, "%s,", iter.Value())
   499  			} else {
   500  				fmt.Fprintf(&buf, ".,")
   501  			}
   502  			if hasRange {
   503  				start, end := iter.RangeBounds()
   504  				fmt.Fprintf(&buf, "[%s-%s)", start, end)
   505  				writeRangeKeys(&buf, iter)
   506  			} else {
   507  				fmt.Fprintf(&buf, ".")
   508  			}
   509  			fmt.Fprintln(&buf, ")")
   510  		}
   511  		return strings.TrimSpace(buf.String())
   512  	}
   513  	// Scanning the iterator should only see the point key written before the
   514  	// iterator was constructed.
   515  	require.Equal(t, `foo: (foo,.)`, scanIter())
   516  
   517  	// After calling SetOptions, the iterator should still only see the point
   518  	// key written before the iterator was constructed. SetOptions refreshes the
   519  	// iterator's view of its own indexed batch, but not committed state.
   520  	iter.SetOptions(&iterOpts)
   521  	require.Equal(t, `foo: (foo,.)`, scanIter())
   522  }
   523  
   524  func TestFlushableBatchReset(t *testing.T) {
   525  	var b Batch
   526  	b.flushable = newFlushableBatch(&b, DefaultComparer)
   527  
   528  	b.Reset()
   529  	require.Nil(t, b.flushable)
   530  }
   531  
   532  func TestBatchIncrement(t *testing.T) {
   533  	testCases := []uint32{
   534  		0x00000000,
   535  		0x00000001,
   536  		0x00000002,
   537  		0x0000007f,
   538  		0x00000080,
   539  		0x000000fe,
   540  		0x000000ff,
   541  		0x00000100,
   542  		0x00000101,
   543  		0x000001ff,
   544  		0x00000200,
   545  		0x00000fff,
   546  		0x00001234,
   547  		0x0000fffe,
   548  		0x0000ffff,
   549  		0x00010000,
   550  		0x00010001,
   551  		0x000100fe,
   552  		0x000100ff,
   553  		0x00020100,
   554  		0x03fffffe,
   555  		0x03ffffff,
   556  		0x04000000,
   557  		0x04000001,
   558  		0x7fffffff,
   559  		0xfffffffe,
   560  	}
   561  	for _, tc := range testCases {
   562  		var buf [batchHeaderLen]byte
   563  		binary.LittleEndian.PutUint32(buf[8:12], tc)
   564  		var b Batch
   565  		b.SetRepr(buf[:])
   566  		b.count++
   567  		got := binary.LittleEndian.Uint32(b.Repr()[8:12])
   568  		want := tc + 1
   569  		if got != want {
   570  			t.Errorf("input=%d: got %d, want %d", tc, got, want)
   571  		}
   572  		_, count := ReadBatch(b.Repr())
   573  		if got != want {
   574  			t.Errorf("input=%d: got %d, want %d", tc, count, want)
   575  		}
   576  	}
   577  
   578  	err := func() (err error) {
   579  		defer func() {
   580  			if v := recover(); v != nil {
   581  				if verr, ok := v.(error); ok {
   582  					err = verr
   583  				}
   584  			}
   585  		}()
   586  		var buf [batchHeaderLen]byte
   587  		binary.LittleEndian.PutUint32(buf[8:12], 0xffffffff)
   588  		var b Batch
   589  		b.SetRepr(buf[:])
   590  		b.count++
   591  		b.Repr()
   592  		return nil
   593  	}()
   594  	if err != ErrInvalidBatch {
   595  		t.Fatalf("expected %v, but found %v", ErrInvalidBatch, err)
   596  	}
   597  }
   598  
   599  func TestBatchOpDoesIncrement(t *testing.T) {
   600  	var b Batch
   601  	key := []byte("foo")
   602  	value := []byte("bar")
   603  
   604  	if b.Count() != 0 {
   605  		t.Fatalf("new batch has a nonzero count: %d", b.Count())
   606  	}
   607  
   608  	// Should increment count by 1
   609  	_ = b.Set(key, value, nil)
   610  	if b.Count() != 1 {
   611  		t.Fatalf("expected count: %d, got %d", 1, b.Count())
   612  	}
   613  
   614  	var b2 Batch
   615  	// Should increment count by 1 each
   616  	_ = b2.Set(key, value, nil)
   617  	_ = b2.Delete(key, nil)
   618  	if b2.Count() != 2 {
   619  		t.Fatalf("expected count: %d, got %d", 2, b2.Count())
   620  	}
   621  
   622  	// Should increment count by b2.count()
   623  	_ = b.Apply(&b2, nil)
   624  	if b.Count() != 3 {
   625  		t.Fatalf("expected count: %d, got %d", 3, b.Count())
   626  	}
   627  
   628  	// Should increment count by 1
   629  	_ = b.Merge(key, value, nil)
   630  	if b.Count() != 4 {
   631  		t.Fatalf("expected count: %d, got %d", 4, b.Count())
   632  	}
   633  
   634  	// Should NOT increment count.
   635  	_ = b.LogData([]byte("foobarbaz"), nil)
   636  	if b.Count() != 4 {
   637  		t.Fatalf("expected count: %d, got %d", 4, b.Count())
   638  	}
   639  }
   640  
   641  func TestBatchGet(t *testing.T) {
   642  	testCases := []struct {
   643  		method       string
   644  		memTableSize int
   645  	}{
   646  		{"build", 64 << 20},
   647  		{"build", 2 << 10},
   648  		{"apply", 64 << 20},
   649  	}
   650  
   651  	for _, c := range testCases {
   652  		t.Run(fmt.Sprintf("%s,mem=%d", c.method, c.memTableSize), func(t *testing.T) {
   653  			d, err := Open("", &Options{
   654  				FS:           vfs.NewMem(),
   655  				MemTableSize: c.memTableSize,
   656  			})
   657  			if err != nil {
   658  				t.Fatalf("Open: %v", err)
   659  			}
   660  			defer d.Close()
   661  			var b *Batch
   662  
   663  			datadriven.RunTest(t, "testdata/batch_get", func(td *datadriven.TestData) string {
   664  				switch td.Cmd {
   665  				case "define":
   666  					switch c.method {
   667  					case "build":
   668  						b = d.NewIndexedBatch()
   669  					case "apply":
   670  						b = d.NewBatch()
   671  					}
   672  
   673  					if err := runBatchDefineCmd(td, b); err != nil {
   674  						return err.Error()
   675  					}
   676  
   677  					switch c.method {
   678  					case "apply":
   679  						tmp := d.NewIndexedBatch()
   680  						tmp.Apply(b, nil)
   681  						b = tmp
   682  					}
   683  					return ""
   684  
   685  				case "commit":
   686  					if err := b.Commit(nil); err != nil {
   687  						return err.Error()
   688  					}
   689  					b = nil
   690  					return ""
   691  
   692  				case "get":
   693  					if len(td.CmdArgs) != 1 {
   694  						return fmt.Sprintf("%s expects 1 argument", td.Cmd)
   695  					}
   696  					v, closer, err := b.Get([]byte(td.CmdArgs[0].String()))
   697  					if err != nil {
   698  						return err.Error()
   699  					}
   700  					defer closer.Close()
   701  					return string(v)
   702  
   703  				default:
   704  					return fmt.Sprintf("unknown command: %s", td.Cmd)
   705  				}
   706  			})
   707  		})
   708  	}
   709  }
   710  
   711  func TestBatchIter(t *testing.T) {
   712  	var b *Batch
   713  
   714  	for _, method := range []string{"build", "apply"} {
   715  		for _, testdata := range []string{
   716  			"testdata/internal_iter_next", "testdata/internal_iter_bounds"} {
   717  			t.Run(method, func(t *testing.T) {
   718  				datadriven.RunTest(t, testdata, func(d *datadriven.TestData) string {
   719  					switch d.Cmd {
   720  					case "define":
   721  						switch method {
   722  						case "build":
   723  							b = newIndexedBatch(nil, DefaultComparer)
   724  						case "apply":
   725  							b = newBatch(nil)
   726  						}
   727  
   728  						for _, key := range strings.Split(d.Input, "\n") {
   729  							j := strings.Index(key, ":")
   730  							ikey := base.ParseInternalKey(key[:j])
   731  							value := []byte(key[j+1:])
   732  							b.Set(ikey.UserKey, value, nil)
   733  						}
   734  
   735  						switch method {
   736  						case "apply":
   737  							tmp := newIndexedBatch(nil, DefaultComparer)
   738  							tmp.Apply(b, nil)
   739  							b = tmp
   740  						}
   741  						return ""
   742  
   743  					case "iter":
   744  						var options IterOptions
   745  						for _, arg := range d.CmdArgs {
   746  							switch arg.Key {
   747  							case "lower":
   748  								if len(arg.Vals) != 1 {
   749  									return fmt.Sprintf(
   750  										"%s expects at most 1 value for lower", d.Cmd)
   751  								}
   752  								options.LowerBound = []byte(arg.Vals[0])
   753  							case "upper":
   754  								if len(arg.Vals) != 1 {
   755  									return fmt.Sprintf(
   756  										"%s expects at most 1 value for upper", d.Cmd)
   757  								}
   758  								options.UpperBound = []byte(arg.Vals[0])
   759  							default:
   760  								return fmt.Sprintf("unknown arg: %s", arg.Key)
   761  							}
   762  						}
   763  						iter := b.newInternalIter(&options)
   764  						defer iter.Close()
   765  						return runInternalIterCmd(d, iter)
   766  
   767  					default:
   768  						return fmt.Sprintf("unknown command: %s", d.Cmd)
   769  					}
   770  				})
   771  			})
   772  		}
   773  	}
   774  }
   775  
   776  func TestBatchRangeOps(t *testing.T) {
   777  	var b *Batch
   778  
   779  	datadriven.RunTest(t, "testdata/batch_range_ops", func(td *datadriven.TestData) string {
   780  		switch td.Cmd {
   781  		case "clear":
   782  			b = nil
   783  			return ""
   784  
   785  		case "apply":
   786  			if b == nil {
   787  				b = newIndexedBatch(nil, DefaultComparer)
   788  			}
   789  			t := newBatch(nil)
   790  			if err := runBatchDefineCmd(td, t); err != nil {
   791  				return err.Error()
   792  			}
   793  			if err := b.Apply(t, nil); err != nil {
   794  				return err.Error()
   795  			}
   796  			return ""
   797  
   798  		case "define":
   799  			if b == nil {
   800  				b = newIndexedBatch(nil, DefaultComparer)
   801  			}
   802  			if err := runBatchDefineCmd(td, b); err != nil {
   803  				return err.Error()
   804  			}
   805  			return ""
   806  
   807  		case "scan":
   808  			if len(td.CmdArgs) > 1 {
   809  				return fmt.Sprintf("%s expects at most 1 argument", td.Cmd)
   810  			}
   811  			var fragmentIter keyspan.FragmentIterator
   812  			var internalIter base.InternalIterator
   813  			if len(td.CmdArgs) == 1 {
   814  				switch td.CmdArgs[0].String() {
   815  				case "range-del":
   816  					fragmentIter = b.newRangeDelIter(nil, math.MaxUint64)
   817  					defer fragmentIter.Close()
   818  				case "range-key":
   819  					fragmentIter = b.newRangeKeyIter(nil, math.MaxUint64)
   820  					defer fragmentIter.Close()
   821  				default:
   822  					return fmt.Sprintf("%s unknown argument %s", td.Cmd, td.CmdArgs[0])
   823  				}
   824  			} else {
   825  				internalIter = b.newInternalIter(nil)
   826  				defer internalIter.Close()
   827  			}
   828  
   829  			var buf bytes.Buffer
   830  			if fragmentIter != nil {
   831  				for s := fragmentIter.First(); s != nil; s = fragmentIter.Next() {
   832  					for i := range s.Keys {
   833  						s.Keys[i].Trailer = base.MakeTrailer(
   834  							s.Keys[i].SeqNum()&^base.InternalKeySeqNumBatch,
   835  							s.Keys[i].Kind(),
   836  						)
   837  					}
   838  					fmt.Fprintln(&buf, s)
   839  				}
   840  			} else {
   841  				for k, v := internalIter.First(); k != nil; k, v = internalIter.Next() {
   842  					k.SetSeqNum(k.SeqNum() &^ InternalKeySeqNumBatch)
   843  					fmt.Fprintf(&buf, "%s:%s\n", k, v)
   844  				}
   845  			}
   846  			return buf.String()
   847  
   848  		default:
   849  			return fmt.Sprintf("unknown command: %s", td.Cmd)
   850  		}
   851  	})
   852  }
   853  
   854  func TestBatchTooLarge(t *testing.T) {
   855  	var b Batch
   856  	var result interface{}
   857  	func() {
   858  		defer func() {
   859  			if r := recover(); r != nil {
   860  				result = r
   861  			}
   862  		}()
   863  		b.grow(maxBatchSize)
   864  	}()
   865  	require.EqualValues(t, ErrBatchTooLarge, result)
   866  }
   867  
   868  func TestFlushableBatchIter(t *testing.T) {
   869  	var b *flushableBatch
   870  	datadriven.RunTest(t, "testdata/internal_iter_next", func(d *datadriven.TestData) string {
   871  		switch d.Cmd {
   872  		case "define":
   873  			batch := newBatch(nil)
   874  			for _, key := range strings.Split(d.Input, "\n") {
   875  				j := strings.Index(key, ":")
   876  				ikey := base.ParseInternalKey(key[:j])
   877  				value := []byte(fmt.Sprint(ikey.SeqNum()))
   878  				batch.Set(ikey.UserKey, value, nil)
   879  			}
   880  			b = newFlushableBatch(batch, DefaultComparer)
   881  			return ""
   882  
   883  		case "iter":
   884  			iter := b.newIter(nil)
   885  			defer iter.Close()
   886  			return runInternalIterCmd(d, iter)
   887  
   888  		default:
   889  			return fmt.Sprintf("unknown command: %s", d.Cmd)
   890  		}
   891  	})
   892  }
   893  
   894  func TestFlushableBatch(t *testing.T) {
   895  	var b *flushableBatch
   896  	datadriven.RunTest(t, "testdata/flushable_batch", func(d *datadriven.TestData) string {
   897  		switch d.Cmd {
   898  		case "define":
   899  			batch := newBatch(nil)
   900  			for _, key := range strings.Split(d.Input, "\n") {
   901  				j := strings.Index(key, ":")
   902  				ikey := base.ParseInternalKey(key[:j])
   903  				value := []byte(fmt.Sprint(ikey.SeqNum()))
   904  				switch ikey.Kind() {
   905  				case InternalKeyKindDelete:
   906  					require.NoError(t, batch.Delete(ikey.UserKey, nil))
   907  				case InternalKeyKindSet:
   908  					require.NoError(t, batch.Set(ikey.UserKey, value, nil))
   909  				case InternalKeyKindMerge:
   910  					require.NoError(t, batch.Merge(ikey.UserKey, value, nil))
   911  				case InternalKeyKindRangeDelete:
   912  					require.NoError(t, batch.DeleteRange(ikey.UserKey, value, nil))
   913  				case InternalKeyKindRangeKeyDelete:
   914  					require.NoError(t, batch.RangeKeyDelete(ikey.UserKey, value, nil))
   915  				case InternalKeyKindRangeKeySet:
   916  					require.NoError(t, batch.RangeKeySet(ikey.UserKey, value, value, value, nil))
   917  				case InternalKeyKindRangeKeyUnset:
   918  					require.NoError(t, batch.RangeKeyUnset(ikey.UserKey, value, value, nil))
   919  				}
   920  			}
   921  			b = newFlushableBatch(batch, DefaultComparer)
   922  			return ""
   923  
   924  		case "iter":
   925  			var opts IterOptions
   926  			for _, arg := range d.CmdArgs {
   927  				if len(arg.Vals) != 1 {
   928  					return fmt.Sprintf("%s: %s=<value>", d.Cmd, arg.Key)
   929  				}
   930  				switch arg.Key {
   931  				case "lower":
   932  					opts.LowerBound = []byte(arg.Vals[0])
   933  				case "upper":
   934  					opts.UpperBound = []byte(arg.Vals[0])
   935  				default:
   936  					return fmt.Sprintf("%s: unknown arg: %s", d.Cmd, arg.Key)
   937  				}
   938  			}
   939  
   940  			iter := b.newIter(&opts)
   941  			defer iter.Close()
   942  			return runInternalIterCmd(d, iter)
   943  
   944  		case "dump":
   945  			if len(d.CmdArgs) != 1 || len(d.CmdArgs[0].Vals) != 1 || d.CmdArgs[0].Key != "seq" {
   946  				return "dump seq=<value>\n"
   947  			}
   948  			seqNum, err := strconv.Atoi(d.CmdArgs[0].Vals[0])
   949  			if err != nil {
   950  				return err.Error()
   951  			}
   952  			b.setSeqNum(uint64(seqNum))
   953  
   954  			var buf bytes.Buffer
   955  
   956  			iter := newInternalIterAdapter(b.newIter(nil))
   957  			for valid := iter.First(); valid; valid = iter.Next() {
   958  				fmt.Fprintf(&buf, "%s:%s\n", iter.Key(), iter.Value())
   959  			}
   960  			iter.Close()
   961  
   962  			if rangeDelIter := b.newRangeDelIter(nil); rangeDelIter != nil {
   963  				scanKeyspanIterator(&buf, rangeDelIter)
   964  				rangeDelIter.Close()
   965  			}
   966  			if rangeKeyIter := b.newRangeKeyIter(nil); rangeKeyIter != nil {
   967  				scanKeyspanIterator(&buf, rangeKeyIter)
   968  				rangeKeyIter.Close()
   969  			}
   970  			return buf.String()
   971  
   972  		default:
   973  			return fmt.Sprintf("unknown command: %s", d.Cmd)
   974  		}
   975  	})
   976  }
   977  
   978  func TestFlushableBatchDeleteRange(t *testing.T) {
   979  	var fb *flushableBatch
   980  	var input string
   981  
   982  	datadriven.RunTest(t, "testdata/delete_range", func(td *datadriven.TestData) string {
   983  		switch td.Cmd {
   984  		case "clear":
   985  			input = ""
   986  			return ""
   987  
   988  		case "define":
   989  			b := newBatch(nil)
   990  			// NB: We can't actually add to the flushable batch as we can to a
   991  			// memtable (which shares the "testdata/delete_range" data), so we fake
   992  			// it by concatenating the input and rebuilding the flushable batch from
   993  			// scratch.
   994  			input += "\n" + td.Input
   995  			td.Input = input
   996  			if err := runBatchDefineCmd(td, b); err != nil {
   997  				return err.Error()
   998  			}
   999  			fb = newFlushableBatch(b, DefaultComparer)
  1000  			return ""
  1001  
  1002  		case "scan":
  1003  			var buf bytes.Buffer
  1004  			if len(td.CmdArgs) > 1 {
  1005  				return fmt.Sprintf("%s expects at most 1 argument", td.Cmd)
  1006  			}
  1007  			if len(td.CmdArgs) == 1 {
  1008  				if td.CmdArgs[0].String() != "range-del" {
  1009  					return fmt.Sprintf("%s unknown argument %s", td.Cmd, td.CmdArgs[0])
  1010  				}
  1011  				fi := fb.newRangeDelIter(nil)
  1012  				defer fi.Close()
  1013  				scanKeyspanIterator(&buf, fi)
  1014  			} else {
  1015  				ii := fb.newIter(nil)
  1016  				defer ii.Close()
  1017  				scanInternalIterator(&buf, ii)
  1018  			}
  1019  			return buf.String()
  1020  
  1021  		default:
  1022  			return fmt.Sprintf("unknown command: %s", td.Cmd)
  1023  		}
  1024  	})
  1025  }
  1026  
  1027  func scanInternalIterator(w io.Writer, ii internalIterator) {
  1028  	for k, v := ii.First(); k != nil; k, v = ii.Next() {
  1029  		fmt.Fprintf(w, "%s:%s\n", k, v)
  1030  	}
  1031  }
  1032  
  1033  func scanKeyspanIterator(w io.Writer, ki keyspan.FragmentIterator) {
  1034  	for s := ki.First(); s != nil; s = ki.Next() {
  1035  		fmt.Fprintln(w, s)
  1036  	}
  1037  }
  1038  
  1039  func TestFlushableBatchBytesIterated(t *testing.T) {
  1040  	batch := newBatch(nil)
  1041  	for j := 0; j < 1000; j++ {
  1042  		key := make([]byte, 8+j%3)
  1043  		value := make([]byte, 7+j%5)
  1044  		batch.Set(key, value, nil)
  1045  
  1046  		fb := newFlushableBatch(batch, DefaultComparer)
  1047  
  1048  		var bytesIterated uint64
  1049  		it := fb.newFlushIter(nil, &bytesIterated)
  1050  
  1051  		var prevIterated uint64
  1052  		for key, _ := it.First(); key != nil; key, _ = it.Next() {
  1053  			if bytesIterated < prevIterated {
  1054  				t.Fatalf("bytesIterated moved backward: %d < %d", bytesIterated, prevIterated)
  1055  			}
  1056  			prevIterated = bytesIterated
  1057  		}
  1058  
  1059  		expected := fb.inuseBytes()
  1060  		if bytesIterated != expected {
  1061  			t.Fatalf("bytesIterated: got %d, want %d", bytesIterated, expected)
  1062  		}
  1063  	}
  1064  }
  1065  
  1066  func TestEmptyFlushableBatch(t *testing.T) {
  1067  	// Verify that we can create a flushable batch on an empty batch.
  1068  	fb := newFlushableBatch(newBatch(nil), DefaultComparer)
  1069  	it := newInternalIterAdapter(fb.newIter(nil))
  1070  	require.False(t, it.First())
  1071  }
  1072  
  1073  func BenchmarkBatchSet(b *testing.B) {
  1074  	value := make([]byte, 10)
  1075  	for i := range value {
  1076  		value[i] = byte(i)
  1077  	}
  1078  	key := make([]byte, 8)
  1079  	batch := newBatch(nil)
  1080  
  1081  	b.ResetTimer()
  1082  
  1083  	const batchSize = 1000
  1084  	for i := 0; i < b.N; i += batchSize {
  1085  		end := i + batchSize
  1086  		if end > b.N {
  1087  			end = b.N
  1088  		}
  1089  
  1090  		for j := i; j < end; j++ {
  1091  			binary.BigEndian.PutUint64(key, uint64(j))
  1092  			batch.Set(key, value, nil)
  1093  		}
  1094  		batch.Reset()
  1095  	}
  1096  
  1097  	b.StopTimer()
  1098  }
  1099  
  1100  func BenchmarkIndexedBatchSet(b *testing.B) {
  1101  	value := make([]byte, 10)
  1102  	for i := range value {
  1103  		value[i] = byte(i)
  1104  	}
  1105  	key := make([]byte, 8)
  1106  	batch := newIndexedBatch(nil, DefaultComparer)
  1107  
  1108  	b.ResetTimer()
  1109  
  1110  	const batchSize = 1000
  1111  	for i := 0; i < b.N; i += batchSize {
  1112  		end := i + batchSize
  1113  		if end > b.N {
  1114  			end = b.N
  1115  		}
  1116  
  1117  		for j := i; j < end; j++ {
  1118  			binary.BigEndian.PutUint64(key, uint64(j))
  1119  			batch.Set(key, value, nil)
  1120  		}
  1121  		batch.Reset()
  1122  	}
  1123  
  1124  	b.StopTimer()
  1125  }
  1126  
  1127  func BenchmarkBatchSetDeferred(b *testing.B) {
  1128  	value := make([]byte, 10)
  1129  	for i := range value {
  1130  		value[i] = byte(i)
  1131  	}
  1132  	key := make([]byte, 8)
  1133  	batch := newBatch(nil)
  1134  
  1135  	b.ResetTimer()
  1136  
  1137  	const batchSize = 1000
  1138  	for i := 0; i < b.N; i += batchSize {
  1139  		end := i + batchSize
  1140  		if end > b.N {
  1141  			end = b.N
  1142  		}
  1143  
  1144  		for j := i; j < end; j++ {
  1145  			binary.BigEndian.PutUint64(key, uint64(j))
  1146  			deferredOp := batch.SetDeferred(len(key), len(value))
  1147  
  1148  			copy(deferredOp.Key, key)
  1149  			copy(deferredOp.Value, value)
  1150  
  1151  			deferredOp.Finish()
  1152  		}
  1153  		batch.Reset()
  1154  	}
  1155  
  1156  	b.StopTimer()
  1157  }
  1158  
  1159  func BenchmarkIndexedBatchSetDeferred(b *testing.B) {
  1160  	value := make([]byte, 10)
  1161  	for i := range value {
  1162  		value[i] = byte(i)
  1163  	}
  1164  	key := make([]byte, 8)
  1165  	batch := newIndexedBatch(nil, DefaultComparer)
  1166  
  1167  	b.ResetTimer()
  1168  
  1169  	const batchSize = 1000
  1170  	for i := 0; i < b.N; i += batchSize {
  1171  		end := i + batchSize
  1172  		if end > b.N {
  1173  			end = b.N
  1174  		}
  1175  
  1176  		for j := i; j < end; j++ {
  1177  			binary.BigEndian.PutUint64(key, uint64(j))
  1178  			deferredOp := batch.SetDeferred(len(key), len(value))
  1179  
  1180  			copy(deferredOp.Key, key)
  1181  			copy(deferredOp.Value, value)
  1182  
  1183  			deferredOp.Finish()
  1184  		}
  1185  		batch.Reset()
  1186  	}
  1187  
  1188  	b.StopTimer()
  1189  }
  1190  
  1191  func TestBatchMemTableSizeOverflow(t *testing.T) {
  1192  	opts := &Options{
  1193  		FS: vfs.NewMem(),
  1194  	}
  1195  	opts.EnsureDefaults()
  1196  	d, err := Open("", opts)
  1197  	require.NoError(t, err)
  1198  
  1199  	bigValue := make([]byte, 1000)
  1200  	b := d.NewBatch()
  1201  
  1202  	// memTableSize can overflow as a uint32.
  1203  	b.memTableSize = math.MaxUint32 - 50
  1204  	for i := 0; i < 10; i++ {
  1205  		k := fmt.Sprintf("key-%05d", i)
  1206  		require.NoError(t, b.Set([]byte(k), bigValue, nil))
  1207  	}
  1208  	require.Greater(t, b.memTableSize, uint64(math.MaxUint32))
  1209  	require.NoError(t, b.Close())
  1210  	require.NoError(t, d.Close())
  1211  }
  1212  
  1213  // TestBatchSpanCaching stress tests the caching of keyspan.Spans for range
  1214  // tombstones and range keys.
  1215  func TestBatchSpanCaching(t *testing.T) {
  1216  	opts := &Options{
  1217  		Comparer:           testkeys.Comparer,
  1218  		FS:                 vfs.NewMem(),
  1219  		FormatMajorVersion: FormatNewest,
  1220  	}
  1221  	d, err := Open("", opts)
  1222  	require.NoError(t, err)
  1223  	defer d.Close()
  1224  
  1225  	ks := testkeys.Alpha(1)
  1226  	b := d.NewIndexedBatch()
  1227  	for i := 0; i < ks.Count(); i++ {
  1228  		k := testkeys.Key(ks, i)
  1229  		require.NoError(t, b.Set(k, k, nil))
  1230  	}
  1231  
  1232  	seed := int64(time.Now().UnixNano())
  1233  	t.Logf("seed = %d", seed)
  1234  	rng := rand.New(rand.NewSource(seed))
  1235  	iters := make([][]*Iterator, ks.Count())
  1236  	defer func() {
  1237  		for _, keyIters := range iters {
  1238  			for _, iter := range keyIters {
  1239  				_ = iter.Close()
  1240  			}
  1241  		}
  1242  	}()
  1243  
  1244  	// This test begins with one point key for every letter of the alphabet.
  1245  	// Over the course of the test, point keys are 'replaced' with range keys
  1246  	// with narrow bounds from left to right. Iterators are created at random,
  1247  	// sometimes from the batch and sometimes by cloning existing iterators.
  1248  
  1249  	checkIter := func(iter *Iterator, nextKey int) {
  1250  		var i int
  1251  		for valid := iter.First(); valid; valid = iter.Next() {
  1252  			hasPoint, hasRange := iter.HasPointAndRange()
  1253  			require.Equal(t, testkeys.Key(ks, i), iter.Key())
  1254  			if i < nextKey {
  1255  				// This key should not exist as a point key, just a range key.
  1256  				require.False(t, hasPoint)
  1257  				require.True(t, hasRange)
  1258  			} else {
  1259  				require.True(t, hasPoint)
  1260  				require.False(t, hasRange)
  1261  			}
  1262  			i++
  1263  		}
  1264  		require.Equal(t, ks.Count(), i)
  1265  	}
  1266  
  1267  	// Each iteration of the below loop either reads or writes.
  1268  	//
  1269  	// A write iteration writes a new RANGEDEL and RANGEKEYSET into the batch,
  1270  	// covering a single point key seeded above. Writing these two span keys
  1271  	// together 'replaces' the point key with a range key. Each write iteration
  1272  	// ratchets nextWriteKey so the next write iteration will write the next
  1273  	// key.
  1274  	//
  1275  	// A read iteration creates a new iterator and ensures its state is
  1276  	// expected: some prefix of only point keys, followed by a suffix of only
  1277  	// range keys. Iterators created through Clone should observe the point keys
  1278  	// that existed when the cloned iterator was created.
  1279  	for nextWriteKey := 0; nextWriteKey < ks.Count(); {
  1280  		p := rng.Float64()
  1281  		switch {
  1282  		case p < .10: /* 10 % */
  1283  			// Write a new range deletion and range key.
  1284  			start := testkeys.Key(ks, nextWriteKey)
  1285  			end := append(start, 0x00)
  1286  			require.NoError(t, b.DeleteRange(start, end, nil))
  1287  			require.NoError(t, b.RangeKeySet(start, end, nil, []byte("foo"), nil))
  1288  			nextWriteKey++
  1289  		case p < .55: /* 45 % */
  1290  			// Create a new iterator directly from the batch and check that it
  1291  			// observes the correct state.
  1292  			iter := b.NewIter(&IterOptions{KeyTypes: IterKeyTypePointsAndRanges})
  1293  			checkIter(iter, nextWriteKey)
  1294  			iters[nextWriteKey] = append(iters[nextWriteKey], iter)
  1295  		default: /* 45 % */
  1296  			// Create a new iterator through cloning a random existing iterator
  1297  			// and check that it observes the right state.
  1298  			readKey := rng.Intn(nextWriteKey + 1)
  1299  			itersForReadKey := iters[readKey]
  1300  			if len(itersForReadKey) == 0 {
  1301  				continue
  1302  			}
  1303  			iter, err := itersForReadKey[rng.Intn(len(itersForReadKey))].Clone(CloneOptions{})
  1304  			require.NoError(t, err)
  1305  			checkIter(iter, readKey)
  1306  			iters[readKey] = append(iters[readKey], iter)
  1307  		}
  1308  	}
  1309  }