@@ -135,12 +135,12 @@ type MissionControl struct {
135135}
136136
137137// MissionController manages MissionControl instances in various namespaces.
138- //
139- // NOTE: currently it only has a MissionControl in the default namespace.
140138type MissionController struct {
141- cfg * mcConfig
139+ db kvdb.Backend
140+ cfg * mcConfig
141+ defaultMCCfg * MissionControlConfig
142142
143- mc * MissionControl
143+ mc map [ string ] * MissionControl
144144 mu sync.Mutex
145145
146146 // TODO(roasbeef): further counters, if vertex continually unavailable,
@@ -149,12 +149,33 @@ type MissionController struct {
149149 // TODO(roasbeef): also add favorable metrics for nodes
150150}
151151
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 {
154170 m .mu .Lock ()
155171 defer m .mu .Unlock ()
156172
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
158179}
159180
160181// MissionControlConfig defines parameters that control mission control
@@ -259,61 +280,143 @@ func NewMissionController(db kvdb.Backend, self route.Vertex,
259280 return nil , err
260281 }
261282
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+
262375 store , err := newMissionControlStore (
263- newDefaultNamespacedStore ( db ), cfg .MaxMcHistory ,
376+ newNamespacedDB ( m . db , namespace ), cfg .MaxMcHistory ,
264377 cfg .McFlushInterval ,
265378 )
266379 if err != nil {
267380 return nil , err
268381 }
269382
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 ,
278385 state : newMissionControlState (cfg .MinFailureRelaxInterval ),
279386 store : store ,
280387 estimator : cfg .Estimator ,
281388 log : build .NewPrefixLog (
282- fmt .Sprintf ("[%s]:" , DefaultMissionControlNamespace ),
283- log ,
389+ fmt .Sprintf ("[%s]:" , namespace ), log ,
284390 ),
285391 onConfigUpdate : cfg .OnConfigUpdate ,
286392 }
287393
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
296395
297396 return mc , nil
298397}
299398
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 () {
302401 m .mu .Lock ()
303402 defer m .mu .Unlock ()
304403
305- m .mc .store .run ()
404+ for _ , mc := range m .mc {
405+ mc .store .run ()
406+ }
306407}
307408
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 () {
310411 log .Debug ("Stopping mission control store ticker" )
311412 defer log .Debug ("Mission control store ticker stopped" )
312413
313414 m .mu .Lock ()
314415 defer m .mu .Unlock ()
315416
316- m .mc .store .stop ()
417+ for _ , mc := range m .mc {
418+ mc .store .stop ()
419+ }
317420}
318421
319422// init initializes mission control with historical data.
0 commit comments