func runDebugCheckStoreCmd(cmd *cobra.Command, args []string) error { stopper := stop.NewStopper() defer stopper.Stop() if len(args) != 1 { return errors.New("one required argument: dir") } db, err := openStore(cmd, args[0], stopper) if err != nil { return err } // Iterate over the entire range-id-local space. start := roachpb.Key(keys.LocalRangeIDPrefix) end := start.PrefixEnd() replicaInfo := map[roachpb.RangeID]*replicaCheckInfo{} getReplicaInfo := func(rangeID roachpb.RangeID) *replicaCheckInfo { if info, ok := replicaInfo[rangeID]; ok { return info } replicaInfo[rangeID] = &replicaCheckInfo{} return replicaInfo[rangeID] } if _, err := engine.MVCCIterate(context.Background(), db, start, end, hlc.MaxTimestamp, false /* !consistent */, nil, /* txn */ false /* !reverse */, func(kv roachpb.KeyValue) (bool, error) { rangeID, _, suffix, detail, err := keys.DecodeRangeIDKey(kv.Key) if err != nil { return false, err } switch { case bytes.Equal(suffix, keys.LocalRaftTruncatedStateSuffix): var trunc roachpb.RaftTruncatedState if err := kv.Value.GetProto(&trunc); err != nil { return false, err } getReplicaInfo(rangeID).truncatedIndex = trunc.Index case bytes.Equal(suffix, keys.LocalRaftAppliedIndexSuffix): idx, err := kv.Value.GetInt() if err != nil { return false, err } getReplicaInfo(rangeID).appliedIndex = uint64(idx) case bytes.Equal(suffix, keys.LocalRaftLogSuffix): _, index, err := encoding.DecodeUint64Ascending(detail) if err != nil { return false, err } ri := getReplicaInfo(rangeID) if ri.firstIndex == 0 { ri.firstIndex = index ri.lastIndex = index } else { if index != ri.lastIndex+1 { fmt.Printf("range %s: log index anomaly: %v followed by %v\n", rangeID, ri.lastIndex, index) } ri.lastIndex = index } } return false, nil }); err != nil { return err } for rangeID, info := range replicaInfo { if info.truncatedIndex != info.firstIndex-1 { fmt.Printf("range %s: truncated index %v should equal first index %v - 1\n", rangeID, info.truncatedIndex, info.firstIndex) } if info.appliedIndex < info.firstIndex || info.appliedIndex > info.lastIndex { fmt.Printf("range %s: applied index %v should be between first index %v and last index %v\n", rangeID, info.appliedIndex, info.firstIndex, info.lastIndex) } } return nil }
func tryRangeIDKey(kv engine.MVCCKeyValue) (string, error) { if kv.Key.Timestamp != hlc.ZeroTimestamp { return "", fmt.Errorf("range ID keys shouldn't have timestamps: %s", kv.Key) } _, _, suffix, _, err := keys.DecodeRangeIDKey(kv.Key.Key) if err != nil { return "", err } // All range ID keys are stored inline on the metadata. var meta enginepb.MVCCMetadata if err := meta.Unmarshal(kv.Value); err != nil { return "", err } value := roachpb.Value{RawBytes: meta.RawBytes} // Values encoded as protobufs set msg and continue outside the // switch. Other types are handled inside the switch and return. var msg proto.Message switch { case bytes.Equal(suffix, keys.LocalLeaseAppliedIndexSuffix): fallthrough case bytes.Equal(suffix, keys.LocalRaftAppliedIndexSuffix): i, err := value.GetInt() if err != nil { return "", err } return strconv.FormatInt(i, 10), nil case bytes.Equal(suffix, keys.LocalRangeFrozenStatusSuffix): b, err := value.GetBool() if err != nil { return "", err } return strconv.FormatBool(b), nil case bytes.Equal(suffix, keys.LocalAbortCacheSuffix): msg = &roachpb.AbortCacheEntry{} case bytes.Equal(suffix, keys.LocalRangeLastGCSuffix): msg = &hlc.Timestamp{} case bytes.Equal(suffix, keys.LocalRaftTombstoneSuffix): msg = &roachpb.RaftTombstone{} case bytes.Equal(suffix, keys.LocalRaftTruncatedStateSuffix): msg = &roachpb.RaftTruncatedState{} case bytes.Equal(suffix, keys.LocalRangeLeaseSuffix): msg = &roachpb.Lease{} case bytes.Equal(suffix, keys.LocalRangeStatsSuffix): msg = &enginepb.MVCCStats{} case bytes.Equal(suffix, keys.LocalRaftHardStateSuffix): msg = &raftpb.HardState{} case bytes.Equal(suffix, keys.LocalRaftLastIndexSuffix): i, err := value.GetInt() if err != nil { return "", err } return strconv.FormatInt(i, 10), nil case bytes.Equal(suffix, keys.LocalRangeLastVerificationTimestampSuffixDeprecated): msg = &hlc.Timestamp{} case bytes.Equal(suffix, keys.LocalRangeLastReplicaGCTimestampSuffix): msg = &hlc.Timestamp{} default: return "", fmt.Errorf("unknown raft id key %s", suffix) } if err := value.GetProto(msg); err != nil { return "", err } return msg.String(), nil }