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: unquoted, err := unquoteArg(keyStr, false) if err != nil { return err } *k = mvccKey(engine.MakeMVCCMetadataKey(roachpb.Key(unquoted))) 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)() storeCfg := storage.TestStoreConfig(nil) storeCfg.TestingKnobs.DisableSplitQueue = true store, stopper := createTestStoreWithConfig(t, storeCfg) defer stopper.Stop() scan := func(f func(roachpb.KeyValue) (bool, error)) { if _, err := engine.MVCCIterate(context.Background(), store.Engine(), roachpb.KeyMin, roachpb.KeyMax, hlc.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(context.Background(), rg1(store), &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(context.Background(), rg1(store), 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(context.Background(), rg1(store), &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()) } }