github.com/mhilton/juju-juju@v0.0.0-20150901100907-a94dd2c73455/state/pool.go (about)

     1  // Copyright 2015 Canonical Ltd.
     2  // Licensed under the AGPLv3, see LICENCE file for details.
     3  
     4  package state
     5  
     6  import (
     7  	"sync"
     8  
     9  	"github.com/juju/errors"
    10  	"github.com/juju/names"
    11  )
    12  
    13  // NewStatePool returns a new StatePool instance. It takes a State
    14  // connected to the system (state server environment).
    15  func NewStatePool(systemState *State) *StatePool {
    16  	return &StatePool{
    17  		systemState: systemState,
    18  		pool:        make(map[string]*State),
    19  	}
    20  }
    21  
    22  // StatePool is a simple cache of State instances for multiple environments.
    23  type StatePool struct {
    24  	systemState *State
    25  	// mu protects pool
    26  	mu   sync.Mutex
    27  	pool map[string]*State
    28  }
    29  
    30  // Get returns a State for a given environment from the pool, creating
    31  // one if required.
    32  func (p *StatePool) Get(envUUID string) (*State, error) {
    33  	if envUUID == p.systemState.EnvironUUID() {
    34  		return p.systemState, nil
    35  	}
    36  
    37  	p.mu.Lock()
    38  	defer p.mu.Unlock()
    39  
    40  	st, ok := p.pool[envUUID]
    41  	if ok {
    42  		return st, nil
    43  	}
    44  
    45  	st, err := p.systemState.ForEnviron(names.NewEnvironTag(envUUID))
    46  	if err != nil {
    47  		return nil, errors.Annotatef(err, "failed to create state for environment %v", envUUID)
    48  	}
    49  	p.pool[envUUID] = st
    50  	return st, nil
    51  }
    52  
    53  // SystemState returns the State passed in to NewStatePool.
    54  func (p *StatePool) SystemState() *State {
    55  	return p.systemState
    56  }
    57  
    58  // Close closes all State instances in the pool.
    59  func (p *StatePool) Close() error {
    60  	p.mu.Lock()
    61  	defer p.mu.Unlock()
    62  
    63  	var lastErr error
    64  	for _, st := range p.pool {
    65  		err := st.Close()
    66  		if err != nil {
    67  			lastErr = err
    68  		}
    69  	}
    70  	p.pool = make(map[string]*State)
    71  	return errors.Annotate(lastErr, "at least one error closing a state")
    72  }