-
Notifications
You must be signed in to change notification settings - Fork 116
/
def_ref_units_index.go
158 lines (138 loc) · 3.82 KB
/
def_ref_units_index.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
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
package store
import (
"fmt"
"io"
"github.com/jingweno/ccat/Godeps/_workspace/src/github.com/alecthomas/binary"
"github.com/jingweno/ccat/Godeps/_workspace/src/github.com/gogo/protobuf/proto"
"github.com/jingweno/ccat/Godeps/_workspace/src/sourcegraph.com/sourcegraph/srclib/graph"
"github.com/jingweno/ccat/Godeps/_workspace/src/sourcegraph.com/sourcegraph/srclib/store/phtable"
"github.com/jingweno/ccat/Godeps/_workspace/src/sourcegraph.com/sourcegraph/srclib/unit"
)
// NOTE(sqs): There is a lot of duplication here with defFilesIndex and unitFilesIndex.
// defRefUnitsIndex makes it fast to determine which source units
// contain refs to a def.
type defRefUnitsIndex struct {
phtable *phtable.CHD
ready bool
}
var _ interface {
Index
persistedIndex
unitRefIndexBuilder
unitIndex
} = (*defRefUnitsIndex)(nil)
var c_defRefUnitsIndex_getByDef = 0 // counter
func (x *defRefUnitsIndex) String() string { return fmt.Sprintf("defRefUnitsIndex(ready=%v)", x.ready) }
// getByFile returns a list of source units that contain refs to the
// specified def.
func (x *defRefUnitsIndex) getByDef(def graph.RefDefKey) ([]unit.ID2, bool, error) {
vlog.Printf("defRefUnitsIndex.getByDef(%v)", def)
c_defRefUnitsIndex_getByDef++
k, err := proto.Marshal(&def)
if err != nil {
return nil, false, err
}
if x.phtable == nil {
panic("phtable not built/read")
}
v := x.phtable.Get(k)
if v == nil {
return nil, false, nil
}
var us []unit.ID2
if err := binary.Unmarshal(v, &us); err != nil {
return nil, true, err
}
return us, true, nil
}
// Covers implements unitIndex.
func (x *defRefUnitsIndex) Covers(filters interface{}) int {
cov := 0
for _, f := range storeFilters(filters) {
if _, ok := f.(ByRefDefFilter); ok {
cov++
}
}
return cov
}
// Units implements unitIndex.
func (x *defRefUnitsIndex) Units(fs ...UnitFilter) ([]unit.ID2, error) {
for _, f := range fs {
if ff, ok := f.(ByRefDefFilter); ok {
us, found, err := x.getByDef(ff.withEmptyImpliedValues())
if err != nil {
return nil, err
}
if found {
vlog.Printf("defRefUnitsIndex(%v): Found units %v using index.", fs, us)
return us, nil
}
}
}
return nil, nil
}
// Build implements unitRefIndexBuilder.
func (x *defRefUnitsIndex) Build(unitRefIndexes map[unit.ID2]*defRefsIndex) error {
vlog.Printf("defRefUnitsIndex: building inverted def->units index (%d units)...", len(unitRefIndexes))
defToUnits := map[graph.RefDefKey][]unit.ID2{}
for u, x := range unitRefIndexes {
it := x.phtable.Iterate()
for {
if it == nil {
break
}
kb, _ := it.Get()
var def graph.RefDefKey
if err := proto.Unmarshal(kb, &def); err != nil {
return err
}
// Set implied fields.
if def.DefUnit == "" {
def.DefUnit = u.Name
}
if def.DefUnitType == "" {
def.DefUnitType = u.Type
}
defToUnits[def] = append(defToUnits[def], u)
it = it.Next()
}
}
vlog.Printf("defRefUnitsIndex: adding %d index phtable keys...", len(defToUnits))
b := phtable.Builder(len(defToUnits))
for def, units := range defToUnits {
ub, err := binary.Marshal(units)
if err != nil {
return err
}
kb, err := proto.Marshal(&def)
if err != nil {
return err
}
b.Add(kb, ub)
}
vlog.Printf("defRefUnitsIndex: building phtable index...")
h, err := b.Build()
if err != nil {
return err
}
x.phtable = h
x.ready = true
vlog.Printf("defRefUnitsIndex: done building index.")
return nil
}
// Write implements persistedIndex.
func (x *defRefUnitsIndex) Write(w io.Writer) error {
if x.phtable == nil {
panic("no phtable to write")
}
return x.phtable.Write(w)
}
// Read implements persistedIndex.
func (x *defRefUnitsIndex) Read(r io.Reader) error {
var err error
x.phtable, err = phtable.Read(r)
x.ready = (err == nil)
return err
}
// Ready implements persistedIndex.
func (x *defRefUnitsIndex) Ready() bool { return x.ready }