func newReplicaDataIterator(d *roachpb.RangeDescriptor, e engine.Engine) *replicaDataIterator { // The first range in the keyspace starts at KeyMin, which includes the node-local // space. We need the original StartKey to find the range metadata, but the // actual data starts at LocalMax. dataStartKey := d.StartKey.AsRawKey() if d.StartKey.Equal(roachpb.RKeyMin) { dataStartKey = keys.LocalMax } ri := &replicaDataIterator{ ranges: []keyRange{ { start: engine.MVCCEncodeKey(keys.MakeRangeIDPrefix(d.RangeID)), end: engine.MVCCEncodeKey(keys.MakeRangeIDPrefix(d.RangeID + 1)), }, { start: engine.MVCCEncodeKey(keys.MakeRangeKeyPrefix(d.StartKey)), end: engine.MVCCEncodeKey(keys.MakeRangeKeyPrefix(d.EndKey)), }, { start: engine.MVCCEncodeKey(dataStartKey), end: engine.MVCCEncodeKey(d.EndKey.AsRawKey()), }, }, iter: e.NewIterator(), } ri.iter.Seek(ri.ranges[ri.curIndex].start) ri.advance() return ri }
func makeReplicaKeyRanges(d *roachpb.RangeDescriptor) []keyRange { // The first range in the keyspace starts at KeyMin, which includes the // node-local space. We need the original StartKey to find the range // metadata, but the actual data starts at LocalMax. dataStartKey := d.StartKey.AsRawKey() if d.StartKey.Equal(roachpb.RKeyMin) { dataStartKey = keys.LocalMax } return []keyRange{ { start: engine.MakeMVCCMetadataKey(keys.MakeRangeIDPrefix(d.RangeID)), end: engine.MakeMVCCMetadataKey(keys.MakeRangeIDPrefix(d.RangeID + 1)), }, { start: engine.MakeMVCCMetadataKey(keys.MakeRangeKeyPrefix(d.StartKey)), end: engine.MakeMVCCMetadataKey(keys.MakeRangeKeyPrefix(d.EndKey)), }, { start: engine.MakeMVCCMetadataKey(dataStartKey), end: engine.MakeMVCCMetadataKey(d.EndKey.AsRawKey()), }, } }
func (k *mvccKey) Set(value string) error { var typ keyType var keyStr string i := strings.IndexByte(value, ':') if i == -1 { keyStr = value } else { var err error typ, err = parseKeyType(value[:i]) if err != nil { return err } keyStr = value[i+1:] } switch typ { case raw: *k = mvccKey(engine.MakeMVCCMetadataKey(roachpb.Key(keyStr))) case human: key, err := keys.UglyPrint(keyStr) if err != nil { return err } *k = mvccKey(engine.MakeMVCCMetadataKey(key)) case rangeID: fromID, err := parseRangeID(keyStr) if err != nil { return err } *k = mvccKey(engine.MakeMVCCMetadataKey(keys.MakeRangeIDPrefix(fromID))) default: return fmt.Errorf("unknown key type %s", typ) } return nil }
// TestStoreRangeMergeMetadataCleanup tests that all metadata of a // subsumed range is cleaned up on merge. func TestStoreRangeMergeMetadataCleanup(t *testing.T) { defer leaktest.AfterTest(t) store, stopper := createTestStore(t) defer stopper.Stop() scan := func(f func(roachpb.KeyValue) (bool, error)) { if _, err := engine.MVCCIterate(store.Engine(), roachpb.KeyMin, roachpb.KeyMax, roachpb.ZeroTimestamp, true, nil, false, f); err != nil { t.Fatal(err) } } content := roachpb.Key("testing!") // Write some values left of the proposed split key. pArgs := putArgs([]byte("aaa"), content) if _, err := client.SendWrapped(rg1(store), nil, &pArgs); err != nil { t.Fatal(err) } // Collect all the keys. preKeys := make(map[string]struct{}) scan(func(kv roachpb.KeyValue) (bool, error) { preKeys[string(kv.Key)] = struct{}{} return false, nil }) // Split the range. _, bDesc, err := createSplitRanges(store) if err != nil { t.Fatal(err) } // Write some values right of the split key. pArgs = putArgs([]byte("ccc"), content) if _, err := client.SendWrappedWith(rg1(store), nil, roachpb.Header{ RangeID: bDesc.RangeID, }, &pArgs); err != nil { t.Fatal(err) } // Merge the b range back into the a range. args := adminMergeArgs(roachpb.KeyMin) if _, err := client.SendWrapped(rg1(store), nil, &args); err != nil { t.Fatal(err) } // Collect all the keys again. postKeys := make(map[string]struct{}) scan(func(kv roachpb.KeyValue) (bool, error) { postKeys[string(kv.Key)] = struct{}{} return false, nil }) // Compute the new keys. for k := range preKeys { delete(postKeys, k) } // Keep only the subsumed range's local keys. localRangeKeyPrefix := string(keys.MakeRangeIDPrefix(bDesc.RangeID)) for k := range postKeys { if !strings.HasPrefix(k, localRangeKeyPrefix) { delete(postKeys, k) } } if numKeys := len(postKeys); numKeys > 0 { var buf bytes.Buffer fmt.Fprintf(&buf, "%d keys were not cleaned up:\n", numKeys) for k := range postKeys { fmt.Fprintf(&buf, "%q\n", k) } t.Fatal(buf.String()) } }