@@ -194,7 +194,7 @@ type BalancerGroup struct {
194
194
// The corresponding boolean outgoingStarted is used to stop further updates
195
195
// to sub-balancers after they are closed.
196
196
outgoingMu sync.Mutex
197
- outgoingStarted bool
197
+ outgoingClosed bool
198
198
idToBalancerConfig map [string ]* subBalancerWrapper
199
199
// Cache for sub-balancers when they are removed. This is `nil` if caching
200
200
// is disabled by passing `0` for Options.SubBalancerCloseTimeout`.
@@ -224,7 +224,7 @@ type BalancerGroup struct {
224
224
// The corresponding boolean incomingStarted is used to stop further updates
225
225
// from sub-balancers after they are closed.
226
226
incomingMu sync.Mutex
227
- incomingStarted bool // This boolean only guards calls back to ClientConn.
227
+ incomingClosed bool // This boolean only guards calls back to ClientConn.
228
228
scToSubBalancer map [balancer.SubConn ]* subBalancerWrapper
229
229
}
230
230
@@ -265,30 +265,6 @@ func New(opts Options) *BalancerGroup {
265
265
}
266
266
}
267
267
268
- // Start starts the balancer group, including building all the sub-balancers,
269
- // and send the existing addresses to them.
270
- //
271
- // A BalancerGroup can be closed and started later. When a BalancerGroup is
272
- // closed, it can still receive address updates, which will be applied when
273
- // restarted.
274
- func (bg * BalancerGroup ) Start () {
275
- bg .incomingMu .Lock ()
276
- bg .incomingStarted = true
277
- bg .incomingMu .Unlock ()
278
-
279
- bg .outgoingMu .Lock ()
280
- if bg .outgoingStarted {
281
- bg .outgoingMu .Unlock ()
282
- return
283
- }
284
-
285
- for _ , config := range bg .idToBalancerConfig {
286
- config .startBalancer ()
287
- }
288
- bg .outgoingStarted = true
289
- bg .outgoingMu .Unlock ()
290
- }
291
-
292
268
// AddWithClientConn adds a balancer with the given id to the group. The
293
269
// balancer is built with a balancer builder registered with balancerName. The
294
270
// given ClientConn is passed to the newly built balancer instead of the
@@ -299,17 +275,18 @@ func (bg *BalancerGroup) AddWithClientConn(id, balancerName string, cc balancer.
299
275
bg .logger .Infof ("Adding child policy of type %q for child %q" , balancerName , id )
300
276
builder := balancer .Get (balancerName )
301
277
if builder == nil {
302
- return fmt .Errorf ("unregistered balancer name %q" , balancerName )
278
+ return fmt .Errorf ("balancergroup: unregistered balancer name %q" , balancerName )
303
279
}
304
280
305
281
// Store data in static map, and then check to see if bg is started.
306
282
bg .outgoingMu .Lock ()
307
283
defer bg .outgoingMu .Unlock ()
284
+ if bg .outgoingClosed {
285
+ return fmt .Errorf ("balancergroup: already closed" )
286
+ }
308
287
var sbc * subBalancerWrapper
309
- // If outgoingStarted is true, search in the cache. Otherwise, cache is
310
- // guaranteed to be empty, searching is unnecessary. Also, skip the cache if
311
- // caching is disabled.
312
- if bg .outgoingStarted && bg .deletedBalancerCache != nil {
288
+ // Skip searching the cache if disabled.
289
+ if bg .deletedBalancerCache != nil {
313
290
if old , ok := bg .deletedBalancerCache .Remove (id ); ok {
314
291
if bg .logger .V (2 ) {
315
292
bg .logger .Infof ("Removing and reusing child policy of type %q for child %q from the balancer cache" , balancerName , id )
@@ -341,11 +318,7 @@ func (bg *BalancerGroup) AddWithClientConn(id, balancerName string, cc balancer.
341
318
builder : builder ,
342
319
buildOpts : bg .buildOpts ,
343
320
}
344
- if bg .outgoingStarted {
345
- // Only start the balancer if bg is started. Otherwise, we only keep the
346
- // static data.
347
- sbc .startBalancer ()
348
- }
321
+ sbc .startBalancer ()
349
322
} else {
350
323
// When brining back a sub-balancer from cache, re-send the cached
351
324
// picker and state.
@@ -369,6 +342,10 @@ func (bg *BalancerGroup) Remove(id string) {
369
342
bg .logger .Infof ("Removing child policy for child %q" , id )
370
343
371
344
bg .outgoingMu .Lock ()
345
+ if bg .outgoingClosed {
346
+ bg .outgoingMu .Unlock ()
347
+ return
348
+ }
372
349
373
350
sbToRemove , ok := bg .idToBalancerConfig [id ]
374
351
if ! ok {
@@ -379,12 +356,6 @@ func (bg *BalancerGroup) Remove(id string) {
379
356
380
357
// Unconditionally remove the sub-balancer config from the map.
381
358
delete (bg .idToBalancerConfig , id )
382
- if ! bg .outgoingStarted {
383
- // Nothing needs to be done here, since we wouldn't have created the
384
- // sub-balancer.
385
- bg .outgoingMu .Unlock ()
386
- return
387
- }
388
359
389
360
if bg .deletedBalancerCache != nil {
390
361
if bg .logger .V (2 ) {
@@ -424,6 +395,7 @@ func (bg *BalancerGroup) Remove(id string) {
424
395
// cleanup after the timeout.
425
396
func (bg * BalancerGroup ) cleanupSubConns (config * subBalancerWrapper ) {
426
397
bg .incomingMu .Lock ()
398
+ defer bg .incomingMu .Unlock ()
427
399
// Remove SubConns. This is only done after the balancer is
428
400
// actually closed.
429
401
//
@@ -437,18 +409,20 @@ func (bg *BalancerGroup) cleanupSubConns(config *subBalancerWrapper) {
437
409
delete (bg .scToSubBalancer , sc )
438
410
}
439
411
}
440
- bg .incomingMu .Unlock ()
441
412
}
442
413
443
414
// connect attempts to connect to all subConns belonging to sb.
444
415
func (bg * BalancerGroup ) connect (sb * subBalancerWrapper ) {
445
416
bg .incomingMu .Lock ()
417
+ defer bg .incomingMu .Unlock ()
418
+ if bg .incomingClosed {
419
+ return
420
+ }
446
421
for sc , b := range bg .scToSubBalancer {
447
422
if b == sb {
448
423
sc .Connect ()
449
424
}
450
425
}
451
- bg .incomingMu .Unlock ()
452
426
}
453
427
454
428
// Following are actions from the parent grpc.ClientConn, forward to sub-balancers.
@@ -457,6 +431,10 @@ func (bg *BalancerGroup) connect(sb *subBalancerWrapper) {
457
431
// needed.
458
432
func (bg * BalancerGroup ) updateSubConnState (sc balancer.SubConn , state balancer.SubConnState , cb func (balancer.SubConnState )) {
459
433
bg .incomingMu .Lock ()
434
+ if bg .incomingClosed {
435
+ bg .incomingMu .Unlock ()
436
+ return
437
+ }
460
438
if _ , ok := bg .scToSubBalancer [sc ]; ! ok {
461
439
bg .incomingMu .Unlock ()
462
440
return
@@ -468,10 +446,13 @@ func (bg *BalancerGroup) updateSubConnState(sc balancer.SubConn, state balancer.
468
446
bg .incomingMu .Unlock ()
469
447
470
448
bg .outgoingMu .Lock ()
449
+ defer bg .outgoingMu .Unlock ()
450
+ if bg .outgoingClosed {
451
+ return
452
+ }
471
453
if cb != nil {
472
454
cb (state )
473
455
}
474
- bg .outgoingMu .Unlock ()
475
456
}
476
457
477
458
// UpdateSubConnState handles the state for the subconn. It finds the
@@ -485,6 +466,9 @@ func (bg *BalancerGroup) UpdateSubConnState(sc balancer.SubConn, state balancer.
485
466
func (bg * BalancerGroup ) UpdateClientConnState (id string , s balancer.ClientConnState ) error {
486
467
bg .outgoingMu .Lock ()
487
468
defer bg .outgoingMu .Unlock ()
469
+ if bg .outgoingClosed {
470
+ return nil
471
+ }
488
472
if config , ok := bg .idToBalancerConfig [id ]; ok {
489
473
return config .updateClientConnState (s )
490
474
}
@@ -494,10 +478,13 @@ func (bg *BalancerGroup) UpdateClientConnState(id string, s balancer.ClientConnS
494
478
// ResolverError forwards resolver errors to all sub-balancers.
495
479
func (bg * BalancerGroup ) ResolverError (err error ) {
496
480
bg .outgoingMu .Lock ()
481
+ defer bg .outgoingMu .Unlock ()
482
+ if bg .outgoingClosed {
483
+ return
484
+ }
497
485
for _ , config := range bg .idToBalancerConfig {
498
486
config .resolverError (err )
499
487
}
500
- bg .outgoingMu .Unlock ()
501
488
}
502
489
503
490
// Following are actions from sub-balancers, forward to ClientConn.
@@ -514,9 +501,9 @@ func (bg *BalancerGroup) newSubConn(config *subBalancerWrapper, addrs []resolver
514
501
// error. But since we call balancer.stopBalancer when removing the balancer, this
515
502
// shouldn't happen.
516
503
bg .incomingMu .Lock ()
517
- if ! bg .incomingStarted {
504
+ if bg .incomingClosed {
518
505
bg .incomingMu .Unlock ()
519
- return nil , fmt .Errorf ("NewSubConn is called after balancer group is closed" )
506
+ return nil , fmt .Errorf ("balancergroup: NewSubConn is called after balancer group is closed" )
520
507
}
521
508
var sc balancer.SubConn
522
509
oldListener := opts .StateListener
@@ -547,31 +534,33 @@ func (bg *BalancerGroup) updateBalancerState(id string, state balancer.State) {
547
534
}
548
535
549
536
// Close closes the balancer. It stops sub-balancers, and removes the subconns.
550
- // The BalancerGroup can be restarted later .
537
+ // When a BalancerGroup is closed, it can not receive further address updates .
551
538
func (bg * BalancerGroup ) Close () {
552
539
bg .incomingMu .Lock ()
553
- if bg .incomingStarted {
554
- bg .incomingStarted = false
555
- // Also remove all SubConns.
556
- for sc := range bg .scToSubBalancer {
557
- sc .Shutdown ()
558
- delete (bg .scToSubBalancer , sc )
559
- }
540
+ bg .incomingClosed = true
541
+ // Also remove all SubConns.
542
+ for sc := range bg .scToSubBalancer {
543
+ sc .Shutdown ()
544
+ delete (bg .scToSubBalancer , sc )
560
545
}
561
546
bg .incomingMu .Unlock ()
562
547
548
+ bg .outgoingMu .Lock ()
549
+ // Setting `outgoingClosed` ensures that no entries are added to
550
+ // `deletedBalancerCache` after this point.
551
+ bg .outgoingClosed = true
552
+ bg .outgoingMu .Unlock ()
553
+
563
554
// Clear(true) runs clear function to close sub-balancers in cache. It
564
555
// must be called out of outgoing mutex.
565
556
if bg .deletedBalancerCache != nil {
566
557
bg .deletedBalancerCache .Clear (true )
567
558
}
568
559
569
560
bg .outgoingMu .Lock ()
570
- if bg .outgoingStarted {
571
- bg .outgoingStarted = false
572
- for _ , config := range bg .idToBalancerConfig {
573
- config .stopBalancer ()
574
- }
561
+ for id , config := range bg .idToBalancerConfig {
562
+ config .stopBalancer ()
563
+ delete (bg .idToBalancerConfig , id )
575
564
}
576
565
bg .outgoingMu .Unlock ()
577
566
}
@@ -581,24 +570,30 @@ func (bg *BalancerGroup) Close() {
581
570
// not supported.
582
571
func (bg * BalancerGroup ) ExitIdle () {
583
572
bg .outgoingMu .Lock ()
573
+ defer bg .outgoingMu .Unlock ()
574
+ if bg .outgoingClosed {
575
+ return
576
+ }
584
577
for _ , config := range bg .idToBalancerConfig {
585
578
if ! config .exitIdle () {
586
579
bg .connect (config )
587
580
}
588
581
}
589
- bg .outgoingMu .Unlock ()
590
582
}
591
583
592
584
// ExitIdleOne instructs the sub-balancer `id` to exit IDLE state, if
593
585
// appropriate and possible.
594
586
func (bg * BalancerGroup ) ExitIdleOne (id string ) {
595
587
bg .outgoingMu .Lock ()
588
+ defer bg .outgoingMu .Unlock ()
589
+ if bg .outgoingClosed {
590
+ return
591
+ }
596
592
if config := bg .idToBalancerConfig [id ]; config != nil {
597
593
if ! config .exitIdle () {
598
594
bg .connect (config )
599
595
}
600
596
}
601
- bg .outgoingMu .Unlock ()
602
597
}
603
598
604
599
// ParseConfig parses a child config list and returns a LB config for the
0 commit comments