forked from hypermodeinc/dgraph
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathdebug.go
128 lines (115 loc) · 3.69 KB
/
debug.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
// +build debug
/*
* Copyright 2022 Dgraph Labs, Inc. and Contributors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package x
import (
"bytes"
"log"
"sort"
"github.com/dgraph-io/badger/v3"
bpb "github.com/dgraph-io/badger/v3/pb"
"github.com/dgraph-io/dgraph/protos/pb"
)
// VerifyPack checks that the Pack should not be nil if the postings exist.
func VerifyPack(plist *pb.PostingList) {
if plist.Pack == nil && len(plist.Postings) > 0 {
log.Panic("UID Pack verification failed: Pack is nil for posting list: %+v", plist)
}
}
// VerifySnapshot iterates over all the keys in badger. For all data keys it checks
// if key is a split key and it verifies if all part are present in badger as well.
func VerifySnapshot(pstore *badger.DB, readTs uint64) {
stream := pstore.NewStreamAt(readTs)
stream.KeyToList = func(key []byte, itr *badger.Iterator) (*bpb.KVList, error) {
for ; itr.Valid(); itr.Next() {
item := itr.Item()
if item.IsDeletedOrExpired() {
break
}
if !bytes.Equal(key, item.Key()) {
// Break out on the first encounter with another key.
break
}
k := item.Key()
parsedKey, kErr := Parse(k)
Checkf(kErr, "Error parsing key: %v, version: %d", k, item.Version())
if !parsedKey.IsData() {
continue
}
err := item.Value(func(v []byte) error {
plist := &pb.PostingList{}
Check(plist.Unmarshal(v))
VerifyPack(plist)
if len(plist.Splits) == 0 {
return nil
}
if plist.Splits[0] != uint64(1) {
log.Panic("First split UID is not 1 baseKey: ", k,
" version ", item.Version())
}
for _, uid := range plist.Splits {
sKey, kErr := SplitKey(k, uid)
Checkf(kErr,
"Error creating split key from base key: %v, version: %d", k,
item.Version())
newTxn := pstore.NewTransactionAt(readTs, false)
_, dbErr := newTxn.Get(sKey)
if dbErr != nil {
log.Panic("Snapshot verification failed: Unable to find splitKey: ",
sKey, "\nbaseKey: ", " version: ", item.Version(),
parsedKey, "\nSplits: ", plist.Splits,
)
}
}
return nil
})
Checkf(err, "Error getting value of key: %v version: %v", k, item.Version())
if item.DiscardEarlierVersions() {
break
}
}
return nil, nil
}
}
// VerifyPostingSplits checks if all the keys from parts are
// present in kvs. Parts is a map of split keys -> postinglist.
func VerifyPostingSplits(kvs []*bpb.KV, plist *pb.PostingList,
parts map[uint64]*pb.PostingList, baseKey []byte) {
if len(plist.Splits) == 0 {
return
}
if plist.Splits[0] != uint64(1) {
log.Panic("Posting split verification failed: First uid of split ",
plist.Splits[0], " is not 1\nPosting: ", plist)
}
for _, uid := range plist.Splits {
if _, ok := parts[uid]; !ok {
log.Panic(uid, " split uid is not present")
}
partKey, kErr := SplitKey(baseKey, uid)
if kErr != nil {
log.Panic("Error while generating splitKey. baseKey: ",
baseKey, " startUid: ", uid)
}
keyIdx := sort.Search(len(kvs), func(i int) bool {
return bytes.Compare(kvs[i].Key, partKey) >= 0
})
if keyIdx == len(kvs) {
log.Panic("Posting split verification failed: ", partKey,
" split key not found\nbaseKey: ", baseKey, "\nPosting: ", plist)
}
}
}