@@ -34,7 +34,7 @@ func ConfigSetup() {
34
34
}
35
35
36
36
type Tree struct {
37
- Items map [string ]* Node
37
+ Items map [string ]* Node // key is the full path of the node.
38
38
}
39
39
40
40
type Node struct {
@@ -54,14 +54,16 @@ func (n *Node) String() string {
54
54
// Implements the the "MetricIndex" interface
55
55
type MemoryIdx struct {
56
56
sync.RWMutex
57
- DefById map [string ]* schema.MetricDefinition
58
- Tree map [int ]* Tree
57
+ FailedDefs map [string ]error
58
+ DefById map [string ]* schema.MetricDefinition
59
+ Tree map [int ]* Tree
59
60
}
60
61
61
62
func New () * MemoryIdx {
62
63
return & MemoryIdx {
63
- DefById : make (map [string ]* schema.MetricDefinition ),
64
- Tree : make (map [int ]* Tree ),
64
+ FailedDefs : make (map [string ]error ),
65
+ DefById : make (map [string ]* schema.MetricDefinition ),
66
+ Tree : make (map [int ]* Tree ),
65
67
}
66
68
}
67
69
@@ -80,22 +82,32 @@ func (m *MemoryIdx) Stop() {
80
82
return
81
83
}
82
84
83
- func (m * MemoryIdx ) Add (data * schema.MetricData ) {
85
+ func (m * MemoryIdx ) Add (data * schema.MetricData ) error {
84
86
pre := time .Now ()
85
87
m .Lock ()
86
88
defer m .Unlock ()
89
+ err , ok := m .FailedDefs [data .Id ]
90
+ if ok {
91
+ // if it failed before, it would fail again.
92
+ // there's not much point in doing the work of trying over
93
+ // and over again, and flooding the logs with the same failure.
94
+ // so just trigger the stats metric as if we tried again
95
+ idxFail .Inc (1 )
96
+ return err
97
+ }
87
98
existing , ok := m .DefById [data .Id ]
88
99
if ok {
89
100
log .Debug ("metricDef with id %s already in index." , data .Id )
90
101
existing .LastUpdate = data .Time
91
102
idxOk .Inc (1 )
92
103
idxAddDuration .Value (time .Since (pre ))
93
- return
104
+ return nil
94
105
}
95
106
96
107
def := schema .MetricDefinitionFromMetricData (data )
97
- m .add (def )
108
+ err = m .add (def )
98
109
idxAddDuration .Value (time .Since (pre ))
110
+ return err
99
111
}
100
112
101
113
// Used to rebuild the index from an existing set of metricDefinitions.
@@ -114,7 +126,7 @@ func (m *MemoryIdx) Load(defs []schema.MetricDefinition) {
114
126
m .Unlock ()
115
127
}
116
128
117
- func (m * MemoryIdx ) AddDef (def * schema.MetricDefinition ) {
129
+ func (m * MemoryIdx ) AddDef (def * schema.MetricDefinition ) error {
118
130
pre := time .Now ()
119
131
m .Lock ()
120
132
defer m .Unlock ()
@@ -123,14 +135,14 @@ func (m *MemoryIdx) AddDef(def *schema.MetricDefinition) {
123
135
existing .LastUpdate = def .LastUpdate
124
136
idxOk .Inc (1 )
125
137
idxAddDuration .Value (time .Since (pre ))
126
- return
138
+ return nil
127
139
}
128
- m .add (def )
140
+ err := m .add (def )
129
141
idxAddDuration .Value (time .Since (pre ))
142
+ return err
130
143
}
131
144
132
- func (m * MemoryIdx ) add (def * schema.MetricDefinition ) {
133
- m .DefById [def .Id ] = def
145
+ func (m * MemoryIdx ) add (def * schema.MetricDefinition ) error {
134
146
path := def .Name
135
147
//first check to see if a tree has been created for this OrgId
136
148
tree , ok := m .Tree [def .OrgId ]
@@ -153,28 +165,36 @@ func (m *MemoryIdx) add(def *schema.MetricDefinition) {
153
165
if ! node .Leaf {
154
166
//bad data. A path cant be both a leaf and a branch.
155
167
log .Info ("memory-idx: Bad data, a path can not be both a leaf and a branch. %d - %s" , def .OrgId , path )
168
+ m .FailedDefs [def .Id ] = idx .BothBranchAndLeaf
156
169
idxFail .Inc (1 )
157
- return
170
+ return idx . BothBranchAndLeaf
158
171
}
159
172
log .Debug ("memory-idx: existing index entry for %s. Adding %s as child" , path , def .Id )
160
173
node .Children = append (node .Children , def .Id )
174
+ m .DefById [def .Id ] = def
161
175
idxOk .Inc (1 )
162
- return
176
+ return nil
163
177
}
164
178
}
165
179
// now walk backwards through the node path to find the first branch which exists that
166
180
// this path extends.
167
181
nodes := strings .Split (path , "." )
168
- startPos := 0
182
+
183
+ // if we're trying to insert foo.bar.baz.quux then we see if we can insert it under (in this order):
184
+ // - foo.bar.baz (if found, startPos is 3)
185
+ // - foo.bar (if found, startPos is 2)
186
+ // - foo (if found, startPos is 1)
187
+ startPos := 0 // the index of the first word that is not part of the prefix
169
188
var startNode * Node
170
189
if len (nodes ) > 1 {
171
190
for i := len (nodes ) - 1 ; i > 0 ; i -- {
172
191
branch := strings .Join (nodes [0 :i ], "." )
173
192
if n , ok := tree .Items [branch ]; ok {
174
193
if n .Leaf {
175
194
log .Info ("memory-idx: Branches cant be added to a leaf node. %d - %s" , def .OrgId , path )
195
+ m .FailedDefs [def .Id ] = idx .BranchUnderLeaf
176
196
idxFail .Inc (1 )
177
- return
197
+ return idx . BranchUnderLeaf
178
198
}
179
199
log .Debug ("memory-idx: Found branch %s which metricDef %s is a descendant of" , branch , path )
180
200
startNode = n
@@ -211,8 +231,9 @@ func (m *MemoryIdx) add(def *schema.MetricDefinition) {
211
231
Path : path ,
212
232
Children : []string {def .Id },
213
233
}
234
+ m .DefById [def .Id ] = def
214
235
idxOk .Inc (1 )
215
- return
236
+ return nil
216
237
}
217
238
218
239
func (m * MemoryIdx ) Get (id string ) (schema.MetricDefinition , error ) {
@@ -285,6 +306,11 @@ func (m *MemoryIdx) find(orgId int, pattern string) ([]*Node, error) {
285
306
}
286
307
287
308
nodes := strings .Split (pattern , "." )
309
+
310
+ // pos is the index of the last node we know for sure
311
+ // for a query like foo.bar.baz, pos is 2
312
+ // for a query like foo.bar.* or foo.bar, pos is 1
313
+ // for a query like foo.b*.baz, pos is 0
288
314
pos := len (nodes ) - 1
289
315
for i := 0 ; i < len (nodes ); i ++ {
290
316
if strings .ContainsAny (nodes [i ], "*{}[]?" ) {
@@ -435,6 +461,12 @@ func (m *MemoryIdx) Delete(orgId int, pattern string) ([]schema.MetricDefinition
435
461
if err != nil {
436
462
return nil , err
437
463
}
464
+
465
+ // by deleting one or more nodes in the tree, any defs that previously failed may now
466
+ // be able to be added. An easy way to support this is just reset this map and give them
467
+ // all a chance again
468
+ m .FailedDefs = make (map [string ]error )
469
+
438
470
deletedDefs := make ([]schema.MetricDefinition , 0 )
439
471
for _ , f := range found {
440
472
deleted , err := m .delete (orgId , f )
@@ -469,7 +501,7 @@ func (m *MemoryIdx) delete(orgId int, n *Node) ([]schema.MetricDefinition, error
469
501
deletedDefs := make ([]schema.MetricDefinition , len (n .Children ))
470
502
// delete the metricDefs
471
503
for i , id := range n .Children {
472
- log .Debug ("memory-idx: deleteing %s from index" , id )
504
+ log .Debug ("memory-idx: deleting %s from index" , id )
473
505
deletedDefs [i ] = * m .DefById [id ]
474
506
delete (m .DefById , id )
475
507
}
0 commit comments