github.com/resin-io/docker@v1.13.1/pkg/discovery/memory/memory.go (about)

     1  package memory
     2  
     3  import (
     4  	"sync"
     5  	"time"
     6  
     7  	"github.com/docker/docker/pkg/discovery"
     8  )
     9  
    10  // Discovery implements a discovery backend that keeps
    11  // data in memory.
    12  type Discovery struct {
    13  	heartbeat time.Duration
    14  	values    []string
    15  	mu        sync.Mutex
    16  }
    17  
    18  func init() {
    19  	Init()
    20  }
    21  
    22  // Init registers the memory backend on demand.
    23  func Init() {
    24  	discovery.Register("memory", &Discovery{})
    25  }
    26  
    27  // Initialize sets the heartbeat for the memory backend.
    28  func (s *Discovery) Initialize(_ string, heartbeat time.Duration, _ time.Duration, _ map[string]string) error {
    29  	s.heartbeat = heartbeat
    30  	s.values = make([]string, 0)
    31  	return nil
    32  }
    33  
    34  // Watch sends periodic discovery updates to a channel.
    35  func (s *Discovery) Watch(stopCh <-chan struct{}) (<-chan discovery.Entries, <-chan error) {
    36  	ch := make(chan discovery.Entries)
    37  	errCh := make(chan error)
    38  	ticker := time.NewTicker(s.heartbeat)
    39  
    40  	go func() {
    41  		defer close(errCh)
    42  		defer close(ch)
    43  
    44  		// Send the initial entries if available.
    45  		var currentEntries discovery.Entries
    46  		var err error
    47  
    48  		s.mu.Lock()
    49  		if len(s.values) > 0 {
    50  			currentEntries, err = discovery.CreateEntries(s.values)
    51  		}
    52  		s.mu.Unlock()
    53  
    54  		if err != nil {
    55  			errCh <- err
    56  		} else if currentEntries != nil {
    57  			ch <- currentEntries
    58  		}
    59  
    60  		// Periodically send updates.
    61  		for {
    62  			select {
    63  			case <-ticker.C:
    64  				s.mu.Lock()
    65  				newEntries, err := discovery.CreateEntries(s.values)
    66  				s.mu.Unlock()
    67  				if err != nil {
    68  					errCh <- err
    69  					continue
    70  				}
    71  
    72  				// Check if the file has really changed.
    73  				if !newEntries.Equals(currentEntries) {
    74  					ch <- newEntries
    75  				}
    76  				currentEntries = newEntries
    77  			case <-stopCh:
    78  				ticker.Stop()
    79  				return
    80  			}
    81  		}
    82  	}()
    83  
    84  	return ch, errCh
    85  }
    86  
    87  // Register adds a new address to the discovery.
    88  func (s *Discovery) Register(addr string) error {
    89  	s.mu.Lock()
    90  	s.values = append(s.values, addr)
    91  	s.mu.Unlock()
    92  	return nil
    93  }