github.com/whamcloud/lemur@v0.0.0-20190827193804-4655df8a52af/cmd/lhsmd/agent/endpoints.go (about)

     1  // Copyright (c) 2018 DDN. All rights reserved.
     2  // Use of this source code is governed by a MIT-style
     3  // license that can be found in the LICENSE file.
     4  
     5  package agent
     6  
     7  import (
     8  	"errors"
     9  	"sync"
    10  	"sync/atomic"
    11  )
    12  
    13  type (
    14  	// Handle is an endpoint handle (unique id)
    15  	Handle uint64
    16  
    17  	// Endpoints represents a collection of Endpoints and their handles
    18  	Endpoints struct {
    19  		sync.Mutex
    20  		nextHandle int64
    21  		endpoints  map[uint32]Endpoint
    22  		handles    map[Handle]uint32
    23  	}
    24  
    25  	// Endpoint defines an interface for HSM backends
    26  	Endpoint interface {
    27  		Send(*Action)
    28  	}
    29  )
    30  
    31  // NewEndpoints returns a new *Endpoints instance
    32  func NewEndpoints() *Endpoints {
    33  	return &Endpoints{
    34  		endpoints: make(map[uint32]Endpoint),
    35  		handles:   make(map[Handle]uint32),
    36  	}
    37  }
    38  
    39  // Get returns an Endpoint or nil, given a lookup id
    40  func (all *Endpoints) Get(a uint32) (Endpoint, bool) {
    41  	all.Lock()
    42  	defer all.Unlock()
    43  	return all.get(a)
    44  }
    45  
    46  // GetWithHandle returns an Endpoint or nil, given a Handle
    47  func (all *Endpoints) GetWithHandle(h *Handle) (Endpoint, bool) {
    48  	all.Lock()
    49  	defer all.Unlock()
    50  	return all.getWithHandle(h)
    51  }
    52  
    53  func (all *Endpoints) get(a uint32) (Endpoint, bool) {
    54  	// all must already be locked.
    55  	e, ok := all.endpoints[a]
    56  	if !ok {
    57  		return nil, ok
    58  	}
    59  	return e, true
    60  }
    61  
    62  func (all *Endpoints) getWithHandle(h *Handle) (Endpoint, bool) {
    63  	// all must already be locked.
    64  	a, ok := all.handles[*h]
    65  	if !ok {
    66  		return nil, ok
    67  	}
    68  
    69  	return all.get(a)
    70  }
    71  
    72  func (all *Endpoints) newHandle() *Handle {
    73  	h := Handle(atomic.AddInt64(&all.nextHandle, 1))
    74  	return &h
    75  }
    76  
    77  // Add registers a new Endpoint
    78  func (all *Endpoints) Add(a uint32, e Endpoint) (*Handle, error) {
    79  	h := all.newHandle()
    80  	all.Lock()
    81  	defer all.Unlock()
    82  
    83  	if _, ok := all.get(a); ok {
    84  		return nil, errors.New("Endpoint already exists")
    85  	}
    86  
    87  	all.endpoints[a] = e
    88  	all.handles[*h] = a
    89  	return h, nil
    90  }
    91  
    92  // NewHandle returns a new *Handle
    93  func (all *Endpoints) NewHandle(a uint32) (*Handle, error) {
    94  	all.Lock()
    95  	defer all.Unlock()
    96  
    97  	if _, ok := all.get(a); !ok {
    98  		return nil, errors.New("Endpoint does not exist")
    99  	}
   100  
   101  	h := all.newHandle()
   102  	all.handles[*h] = a
   103  	return h, nil
   104  
   105  }
   106  
   107  // RemoveHandle removes the given handle from the collection of handles
   108  func (all *Endpoints) RemoveHandle(h *Handle) {
   109  	all.Lock()
   110  	defer all.Unlock()
   111  
   112  	delete(all.handles, *h)
   113  }
   114  
   115  // Remove removes the given handle and its associated Endpoint
   116  func (all *Endpoints) Remove(h *Handle) Endpoint {
   117  	all.Lock()
   118  	defer all.Unlock()
   119  	a, ok := all.handles[*h]
   120  	if !ok {
   121  		return nil
   122  	}
   123  
   124  	if e, ok := all.get(a); ok {
   125  		delete(all.handles, *h)
   126  		delete(all.endpoints, a)
   127  		return e
   128  	}
   129  
   130  	return nil
   131  }