github.com/cockroachdb/cockroach@v20.2.0-alpha.1+incompatible/pkg/kv/kvserver/addressing_test.go (about)

     1  // Copyright 2015 The Cockroach Authors.
     2  //
     3  // Use of this software is governed by the Business Source License
     4  // included in the file licenses/BSL.txt.
     5  //
     6  // As of the Change Date specified in that file, in accordance with
     7  // the Business Source License, use of this software will be governed
     8  // by the Apache License, Version 2.0, included in the file
     9  // licenses/APL.txt.
    10  
    11  package kvserver
    12  
    13  import (
    14  	"bytes"
    15  	"context"
    16  	"fmt"
    17  	"reflect"
    18  	"sort"
    19  	"testing"
    20  	"time"
    21  
    22  	"github.com/cockroachdb/cockroach/pkg/keys"
    23  	"github.com/cockroachdb/cockroach/pkg/kv"
    24  	"github.com/cockroachdb/cockroach/pkg/kv/kvclient/kvcoord"
    25  	"github.com/cockroachdb/cockroach/pkg/roachpb"
    26  	"github.com/cockroachdb/cockroach/pkg/storage"
    27  	"github.com/cockroachdb/cockroach/pkg/testutils"
    28  	"github.com/cockroachdb/cockroach/pkg/util/hlc"
    29  	"github.com/cockroachdb/cockroach/pkg/util/leaktest"
    30  	"github.com/cockroachdb/cockroach/pkg/util/log"
    31  	"github.com/cockroachdb/cockroach/pkg/util/stop"
    32  	"github.com/cockroachdb/errors"
    33  )
    34  
    35  type metaRecord struct {
    36  	key  roachpb.Key
    37  	desc *roachpb.RangeDescriptor
    38  }
    39  type metaSlice []metaRecord
    40  
    41  // Implementation of sort.Interface.
    42  func (ms metaSlice) Len() int           { return len(ms) }
    43  func (ms metaSlice) Swap(i, j int)      { ms[i], ms[j] = ms[j], ms[i] }
    44  func (ms metaSlice) Less(i, j int) bool { return bytes.Compare(ms[i].key, ms[j].key) < 0 }
    45  
    46  func meta1Key(key roachpb.RKey) []byte {
    47  	return testutils.MakeKey(keys.Meta1Prefix, key)
    48  }
    49  
    50  func meta2Key(key roachpb.RKey) []byte {
    51  	return testutils.MakeKey(keys.Meta2Prefix, key)
    52  }
    53  
    54  // TestUpdateRangeAddressing verifies range addressing records are
    55  // correctly updated on creation of new range descriptors.
    56  func TestUpdateRangeAddressing(t *testing.T) {
    57  	defer leaktest.AfterTest(t)()
    58  	stopper := stop.NewStopper()
    59  	defer stopper.Stop(context.Background())
    60  	store, _ := createTestStore(t, testStoreOpts{createSystemRanges: false}, stopper)
    61  	// When split is false, merging treats the right range as the merged
    62  	// range. With merging, expNewLeft indicates the addressing keys we
    63  	// expect to be removed.
    64  	testCases := []struct {
    65  		split                   bool
    66  		leftStart, leftEnd      roachpb.RKey
    67  		rightStart, rightEnd    roachpb.RKey
    68  		leftExpNew, rightExpNew [][]byte
    69  	}{
    70  		// Start out with whole range.
    71  		{false, roachpb.RKeyMin, roachpb.RKeyMax, roachpb.RKeyMin, roachpb.RKeyMax,
    72  			[][]byte{}, [][]byte{meta1Key(roachpb.RKeyMax), meta2Key(roachpb.RKeyMax)}},
    73  		// Split KeyMin-KeyMax at key "a".
    74  		{true, roachpb.RKeyMin, roachpb.RKey("a"), roachpb.RKey("a"), roachpb.RKeyMax,
    75  			[][]byte{meta1Key(roachpb.RKeyMax), meta2Key(roachpb.RKey("a"))}, [][]byte{meta2Key(roachpb.RKeyMax)}},
    76  		// Split "a"-KeyMax at key "z".
    77  		{true, roachpb.RKey("a"), roachpb.RKey("z"), roachpb.RKey("z"), roachpb.RKeyMax,
    78  			[][]byte{meta2Key(roachpb.RKey("z"))}, [][]byte{meta2Key(roachpb.RKeyMax)}},
    79  		// Split "a"-"z" at key "m".
    80  		{true, roachpb.RKey("a"), roachpb.RKey("m"), roachpb.RKey("m"), roachpb.RKey("z"),
    81  			[][]byte{meta2Key(roachpb.RKey("m"))}, [][]byte{meta2Key(roachpb.RKey("z"))}},
    82  		// Split KeyMin-"a" at meta2(m).
    83  		{true, roachpb.RKeyMin, keys.RangeMetaKey(roachpb.RKey("m")), keys.RangeMetaKey(roachpb.RKey("m")), roachpb.RKey("a"),
    84  			[][]byte{meta1Key(roachpb.RKey("m"))}, [][]byte{meta1Key(roachpb.RKeyMax), meta2Key(roachpb.RKey("a"))}},
    85  		// Split meta2(m)-"a" at meta2(z).
    86  		{true, keys.RangeMetaKey(roachpb.RKey("m")), keys.RangeMetaKey(roachpb.RKey("z")), keys.RangeMetaKey(roachpb.RKey("z")), roachpb.RKey("a"),
    87  			[][]byte{meta1Key(roachpb.RKey("z"))}, [][]byte{meta1Key(roachpb.RKeyMax), meta2Key(roachpb.RKey("a"))}},
    88  		// Split meta2(m)-meta2(z) at meta2(r).
    89  		{true, keys.RangeMetaKey(roachpb.RKey("m")), keys.RangeMetaKey(roachpb.RKey("r")), keys.RangeMetaKey(roachpb.RKey("r")), keys.RangeMetaKey(roachpb.RKey("z")),
    90  			[][]byte{meta1Key(roachpb.RKey("r"))}, [][]byte{meta1Key(roachpb.RKey("z"))}},
    91  
    92  		// Now, merge all of our splits backwards...
    93  
    94  		// Merge meta2(m)-meta2(z).
    95  		{false, keys.RangeMetaKey(roachpb.RKey("m")), keys.RangeMetaKey(roachpb.RKey("r")), keys.RangeMetaKey(roachpb.RKey("m")), keys.RangeMetaKey(roachpb.RKey("z")),
    96  			[][]byte{meta1Key(roachpb.RKey("r"))}, [][]byte{meta1Key(roachpb.RKey("z"))}},
    97  		// Merge meta2(m)-"a".
    98  		{false, keys.RangeMetaKey(roachpb.RKey("m")), keys.RangeMetaKey(roachpb.RKey("z")), keys.RangeMetaKey(roachpb.RKey("m")), roachpb.RKey("a"),
    99  			[][]byte{meta1Key(roachpb.RKey("z"))}, [][]byte{meta1Key(roachpb.RKeyMax), meta2Key(roachpb.RKey("a"))}},
   100  		// Merge KeyMin-"a".
   101  		{false, roachpb.RKeyMin, keys.RangeMetaKey(roachpb.RKey("m")), roachpb.RKeyMin, roachpb.RKey("a"),
   102  			[][]byte{meta1Key(roachpb.RKey("m"))}, [][]byte{meta1Key(roachpb.RKeyMax), meta2Key(roachpb.RKey("a"))}},
   103  		// Merge "a"-"z".
   104  		{false, roachpb.RKey("a"), roachpb.RKey("m"), roachpb.RKey("a"), roachpb.RKey("z"),
   105  			[][]byte{meta2Key(roachpb.RKey("m"))}, [][]byte{meta2Key(roachpb.RKey("z"))}},
   106  		// Merge "a"-KeyMax.
   107  		{false, roachpb.RKey("a"), roachpb.RKey("z"), roachpb.RKey("a"), roachpb.RKeyMax,
   108  			[][]byte{meta2Key(roachpb.RKey("z"))}, [][]byte{meta2Key(roachpb.RKeyMax)}},
   109  		// Merge KeyMin-KeyMax.
   110  		{false, roachpb.RKeyMin, roachpb.RKey("a"), roachpb.RKeyMin, roachpb.RKeyMax,
   111  			[][]byte{meta2Key(roachpb.RKey("a"))}, [][]byte{meta1Key(roachpb.RKeyMax), meta2Key(roachpb.RKeyMax)}},
   112  	}
   113  	expMetas := metaSlice{}
   114  
   115  	for i, test := range testCases {
   116  		left := &roachpb.RangeDescriptor{RangeID: roachpb.RangeID(i * 2), StartKey: test.leftStart, EndKey: test.leftEnd}
   117  		right := &roachpb.RangeDescriptor{RangeID: roachpb.RangeID(i*2 + 1), StartKey: test.rightStart, EndKey: test.rightEnd}
   118  		b := &kv.Batch{}
   119  		if test.split {
   120  			if err := splitRangeAddressing(b, left, right); err != nil {
   121  				t.Fatal(err)
   122  			}
   123  		} else {
   124  			if err := mergeRangeAddressing(b, left, right); err != nil {
   125  				t.Fatal(err)
   126  			}
   127  		}
   128  
   129  		// This test constructs an overlapping batch (delete then put on the same
   130  		// key), which is only allowed in a transaction. The test wants to send the
   131  		// batch through the "client" interface (because that's what it used to
   132  		// construct it); unfortunately we can't use the client's transactional
   133  		// interface without sending through a TxnCoordSender (which initializes a
   134  		// transaction id). Also, we need the TxnCoordSender to clean up the
   135  		// intents, otherwise the MVCCScan that the test does below fails.
   136  		actx := testutils.MakeAmbientCtx()
   137  		tcsf := kvcoord.NewTxnCoordSenderFactory(
   138  			kvcoord.TxnCoordSenderFactoryConfig{
   139  				AmbientCtx: actx,
   140  				Settings:   store.cfg.Settings,
   141  				Clock:      store.cfg.Clock,
   142  				Stopper:    stopper,
   143  				Metrics:    kvcoord.MakeTxnMetrics(time.Second),
   144  			},
   145  			store.TestSender(),
   146  		)
   147  		db := kv.NewDB(actx, tcsf, store.cfg.Clock)
   148  		ctx := context.Background()
   149  		txn := kv.NewTxn(ctx, db, 0 /* gatewayNodeID */)
   150  		if err := txn.Run(ctx, b); err != nil {
   151  			t.Fatal(err)
   152  		}
   153  		if err := txn.Commit(ctx); err != nil {
   154  			t.Fatal(err)
   155  		}
   156  		// Scan meta keys directly from engine. We put this in a retry loop
   157  		// because the application of all of a transactions committed writes
   158  		// is not always synchronous with it committing. Cases where the
   159  		// application of a write is asynchronous are:
   160  		// - the write is on a different range than the transaction's record.
   161  		//   Intent resolution will be asynchronous.
   162  		// - the transaction performed a parallel commit. Explicitly committing
   163  		//   the transaction will be asynchronous.
   164  		// - [not yet implemented] the corresponding Raft log entry is committed
   165  		//   but not applied before acknowledging the write. Applying the write
   166  		//   to RocksDB will be asynchronous.
   167  		var kvs []roachpb.KeyValue
   168  		testutils.SucceedsSoon(t, func() error {
   169  			res, err := storage.MVCCScan(ctx, store.Engine(), keys.MetaMin, keys.MetaMax,
   170  				hlc.MaxTimestamp, storage.MVCCScanOptions{})
   171  			if err != nil {
   172  				// Wait for the intent to be resolved.
   173  				if errors.HasType(err, (*roachpb.WriteIntentError)(nil)) {
   174  					return err
   175  				}
   176  				t.Fatal(err)
   177  			}
   178  			kvs = res.KVs
   179  			return nil
   180  		})
   181  		metas := metaSlice{}
   182  		for _, kv := range kvs {
   183  			scannedDesc := &roachpb.RangeDescriptor{}
   184  			if err := kv.Value.GetProto(scannedDesc); err != nil {
   185  				t.Fatal(err)
   186  			}
   187  			metas = append(metas, metaRecord{key: kv.Key, desc: scannedDesc})
   188  		}
   189  
   190  		// Continue to build up the expected metas slice, replacing any earlier
   191  		// version of same key.
   192  		addOrRemoveNew := func(keys [][]byte, desc *roachpb.RangeDescriptor, add bool) {
   193  			for _, n := range keys {
   194  				found := -1
   195  				for i := range expMetas {
   196  					if expMetas[i].key.Equal(roachpb.Key(n)) {
   197  						found = i
   198  						expMetas[i].desc = desc
   199  						break
   200  					}
   201  				}
   202  				if found == -1 && add {
   203  					expMetas = append(expMetas, metaRecord{key: n, desc: desc})
   204  				} else if found != -1 && !add {
   205  					expMetas = append(expMetas[:found], expMetas[found+1:]...)
   206  				}
   207  			}
   208  		}
   209  		addOrRemoveNew(test.leftExpNew, left, test.split /* on split, add; on merge, remove */)
   210  		addOrRemoveNew(test.rightExpNew, right, true)
   211  		sort.Sort(expMetas)
   212  
   213  		if test.split {
   214  			if log.V(1) {
   215  				log.Infof(ctx, "test case %d: split %q-%q at %q", i, left.StartKey, right.EndKey, left.EndKey)
   216  			}
   217  		} else {
   218  			if log.V(1) {
   219  				log.Infof(ctx, "test case %d: merge %q-%q + %q-%q", i, left.StartKey, left.EndKey, left.EndKey, right.EndKey)
   220  			}
   221  		}
   222  		for _, meta := range metas {
   223  			if log.V(1) {
   224  				log.Infof(ctx, "%q", meta.key)
   225  			}
   226  		}
   227  
   228  		if !reflect.DeepEqual(expMetas, metas) {
   229  			t.Errorf("expected metas don't match")
   230  			if len(expMetas) != len(metas) {
   231  				t.Errorf("len(expMetas) != len(metas); %d != %d", len(expMetas), len(metas))
   232  			} else {
   233  				for j, meta := range expMetas {
   234  					if !meta.key.Equal(metas[j].key) {
   235  						fmt.Printf("%d: expected %q vs %q\n", j, meta.key, metas[j].key)
   236  					}
   237  					if !reflect.DeepEqual(meta.desc, metas[j].desc) {
   238  						fmt.Printf("%d: expected %q vs %q and %s vs %s\n", j, meta.key, metas[j].key, meta.desc, metas[j].desc)
   239  					}
   240  				}
   241  			}
   242  		}
   243  	}
   244  }
   245  
   246  // TestUpdateRangeAddressingSplitMeta1 verifies that it's an error to
   247  // attempt to update range addressing records that would allow a split
   248  // of meta1 records.
   249  func TestUpdateRangeAddressingSplitMeta1(t *testing.T) {
   250  	defer leaktest.AfterTest(t)()
   251  	left := &roachpb.RangeDescriptor{StartKey: roachpb.RKeyMin, EndKey: meta1Key(roachpb.RKey("a"))}
   252  	right := &roachpb.RangeDescriptor{StartKey: meta1Key(roachpb.RKey("a")), EndKey: roachpb.RKeyMax}
   253  	if err := splitRangeAddressing(&kv.Batch{}, left, right); err == nil {
   254  		t.Error("expected failure trying to update addressing records for meta1 split")
   255  	}
   256  }