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 }