@@ -135,12 +135,12 @@ type MissionControl struct {
135
135
}
136
136
137
137
// MissionController manages MissionControl instances in various namespaces.
138
- //
139
- // NOTE: currently it only has a MissionControl in the default namespace.
140
138
type MissionController struct {
141
- cfg * mcConfig
139
+ db kvdb.Backend
140
+ cfg * mcConfig
141
+ defaultMCCfg * MissionControlConfig
142
142
143
- mc * MissionControl
143
+ mc map [ string ] * MissionControl
144
144
mu sync.Mutex
145
145
146
146
// TODO(roasbeef): further counters, if vertex continually unavailable,
@@ -149,12 +149,33 @@ type MissionController struct {
149
149
// TODO(roasbeef): also add favorable metrics for nodes
150
150
}
151
151
152
- // GetDefaultStore returns the MissionControl in the default namespace.
153
- func (m * MissionController ) GetDefaultStore () * MissionControl {
152
+ // GetNamespacedStore returns the MissionControl in the given namespace. If one
153
+ // does not yet exist, then it is initialised.
154
+ func (m * MissionController ) GetNamespacedStore (ns string ) (* MissionControl ,
155
+ error ) {
156
+
157
+ m .mu .Lock ()
158
+ defer m .mu .Unlock ()
159
+
160
+ if mc , ok := m .mc [ns ]; ok {
161
+ return mc , nil
162
+ }
163
+
164
+ return m .initMissionControl (ns )
165
+ }
166
+
167
+ // ListNamespaces returns a list of the namespaces that the MissionController
168
+ // is aware of.
169
+ func (m * MissionController ) ListNamespaces () []string {
154
170
m .mu .Lock ()
155
171
defer m .mu .Unlock ()
156
172
157
- return m .mc
173
+ namespaces := make ([]string , 0 , len (m .mc ))
174
+ for ns := range m .mc {
175
+ namespaces = append (namespaces , ns )
176
+ }
177
+
178
+ return namespaces
158
179
}
159
180
160
181
// MissionControlConfig defines parameters that control mission control
@@ -259,61 +280,143 @@ func NewMissionController(db kvdb.Backend, self route.Vertex,
259
280
return nil , err
260
281
}
261
282
283
+ mcCfg := & mcConfig {
284
+ clock : clock .NewDefaultClock (),
285
+ selfNode : self ,
286
+ }
287
+
288
+ mgr := & MissionController {
289
+ db : db ,
290
+ defaultMCCfg : cfg ,
291
+ cfg : mcCfg ,
292
+ mc : make (map [string ]* MissionControl ),
293
+ }
294
+
295
+ if err := mgr .loadMissionControls (); err != nil {
296
+ return nil , err
297
+ }
298
+
299
+ for _ , mc := range mgr .mc {
300
+ if err := mc .init (); err != nil {
301
+ return nil , err
302
+ }
303
+ }
304
+
305
+ return mgr , nil
306
+ }
307
+
308
+ // loadMissionControls initialises a MissionControl in the default namespace if
309
+ // one does not yet exist. It then initialises a MissionControl for all other
310
+ // namespaces found in the DB.
311
+ //
312
+ // NOTE: this should only be called once during MissionController construction.
313
+ func (m * MissionController ) loadMissionControls () error {
314
+ m .mu .Lock ()
315
+ defer m .mu .Unlock ()
316
+
317
+ // Always initialise the default namespace.
318
+ _ , err := m .initMissionControl (DefaultMissionControlNamespace )
319
+ if err != nil {
320
+ return err
321
+ }
322
+
323
+ namespaces := make (map [string ]struct {})
324
+ err = m .db .View (func (tx walletdb.ReadTx ) error {
325
+ mcStoreBkt := tx .ReadBucket (resultsKey )
326
+ if mcStoreBkt == nil {
327
+ return fmt .Errorf ("top level mission control bucket " +
328
+ "not found" )
329
+ }
330
+
331
+ // Iterate through all the keys in the bucket and collect the
332
+ // namespaces.
333
+ return mcStoreBkt .ForEach (func (k , _ []byte ) error {
334
+ // We've already initialised the default namespace so
335
+ // we can skip it.
336
+ if string (k ) == DefaultMissionControlNamespace {
337
+ return nil
338
+ }
339
+
340
+ namespaces [string (k )] = struct {}{}
341
+
342
+ return nil
343
+ })
344
+ }, func () {})
345
+ if err != nil {
346
+ return err
347
+ }
348
+
349
+ // Now, iterate through all the namespaces and initialise them.
350
+ for ns := range namespaces {
351
+ _ , err = m .initMissionControl (ns )
352
+ if err != nil {
353
+ return err
354
+ }
355
+ }
356
+
357
+ return nil
358
+ }
359
+
360
+ // initMissionControl creates a new MissionControl instance with the given
361
+ // namespace if one does not yet exist.
362
+ //
363
+ // NOTE: the MissionController's mutex must be held before calling this method.
364
+ func (m * MissionController ) initMissionControl (namespace string ) (
365
+ * MissionControl , error ) {
366
+
367
+ // If a mission control with this namespace has already been initialised
368
+ // then there is nothing left to do.
369
+ if mc , ok := m .mc [namespace ]; ok {
370
+ return mc , nil
371
+ }
372
+
373
+ cfg := m .defaultMCCfg
374
+
262
375
store , err := newMissionControlStore (
263
- newDefaultNamespacedStore ( db ), cfg .MaxMcHistory ,
376
+ newNamespacedDB ( m . db , namespace ), cfg .MaxMcHistory ,
264
377
cfg .McFlushInterval ,
265
378
)
266
379
if err != nil {
267
380
return nil , err
268
381
}
269
382
270
- mcCfg := & mcConfig {
271
- clock : clock .NewDefaultClock (),
272
- selfNode : self ,
273
- }
274
-
275
- // Create a mission control in the default namespace.
276
- defaultMC := & MissionControl {
277
- cfg : mcCfg ,
383
+ mc := & MissionControl {
384
+ cfg : m .cfg ,
278
385
state : newMissionControlState (cfg .MinFailureRelaxInterval ),
279
386
store : store ,
280
387
estimator : cfg .Estimator ,
281
388
log : build .NewPrefixLog (
282
- fmt .Sprintf ("[%s]:" , DefaultMissionControlNamespace ),
283
- log ,
389
+ fmt .Sprintf ("[%s]:" , namespace ), log ,
284
390
),
285
391
onConfigUpdate : cfg .OnConfigUpdate ,
286
392
}
287
393
288
- mc := & MissionController {
289
- cfg : mcCfg ,
290
- mc : defaultMC ,
291
- }
292
-
293
- if err := mc .mc .init (); err != nil {
294
- return nil , err
295
- }
394
+ m .mc [namespace ] = mc
296
395
297
396
return mc , nil
298
397
}
299
398
300
- // RunStoreTicker runs the mission control store's ticker .
301
- func (m * MissionController ) RunStoreTicker () {
399
+ // RunStoreTickers runs the mission controller store's tickers .
400
+ func (m * MissionController ) RunStoreTickers () {
302
401
m .mu .Lock ()
303
402
defer m .mu .Unlock ()
304
403
305
- m .mc .store .run ()
404
+ for _ , mc := range m .mc {
405
+ mc .store .run ()
406
+ }
306
407
}
307
408
308
- // StopStoreTicker stops the mission control store's ticker .
309
- func (m * MissionController ) StopStoreTicker () {
409
+ // StopStoreTickers stops the mission control store's tickers .
410
+ func (m * MissionController ) StopStoreTickers () {
310
411
log .Debug ("Stopping mission control store ticker" )
311
412
defer log .Debug ("Mission control store ticker stopped" )
312
413
313
414
m .mu .Lock ()
314
415
defer m .mu .Unlock ()
315
416
316
- m .mc .store .stop ()
417
+ for _ , mc := range m .mc {
418
+ mc .store .stop ()
419
+ }
317
420
}
318
421
319
422
// init initializes mission control with historical data.
0 commit comments