github.com/sijibomii/docker@v0.0.0-20231230191044-5cf6ca554647/pkg/registrar/registrar.go (about) 1 // Package registrar provides name registration. It reserves a name to a given key. 2 package registrar 3 4 import ( 5 "errors" 6 "sync" 7 ) 8 9 var ( 10 // ErrNameReserved is an error which is returned when a name is requested to be reserved that already is reserved 11 ErrNameReserved = errors.New("name is reserved") 12 // ErrNameNotReserved is an error which is returned when trying to find a name that is not reserved 13 ErrNameNotReserved = errors.New("name is not reserved") 14 // ErrNoSuchKey is returned when trying to find the names for a key which is not known 15 ErrNoSuchKey = errors.New("provided key does not exist") 16 ) 17 18 // Registrar stores indexes a list of keys and their registered names as well as indexes names and the key that they are registered to 19 // Names must be unique. 20 // Registrar is safe for concurrent access. 21 type Registrar struct { 22 idx map[string][]string 23 names map[string]string 24 mu sync.Mutex 25 } 26 27 // NewRegistrar creates a new Registrar with the an empty index 28 func NewRegistrar() *Registrar { 29 return &Registrar{ 30 idx: make(map[string][]string), 31 names: make(map[string]string), 32 } 33 } 34 35 // Reserve registers a key to a name 36 // Reserve is idempotent 37 // Attempting to reserve a key to a name that already exists results in an `ErrNameReserved` 38 // A name reservation is globally unique 39 func (r *Registrar) Reserve(name, key string) error { 40 r.mu.Lock() 41 defer r.mu.Unlock() 42 43 if k, exists := r.names[name]; exists { 44 if k != key { 45 return ErrNameReserved 46 } 47 return nil 48 } 49 50 r.idx[key] = append(r.idx[key], name) 51 r.names[name] = key 52 return nil 53 } 54 55 // Release releases the reserved name 56 // Once released, a name can be reserved again 57 func (r *Registrar) Release(name string) { 58 r.mu.Lock() 59 defer r.mu.Unlock() 60 61 key, exists := r.names[name] 62 if !exists { 63 return 64 } 65 66 for i, n := range r.idx[key] { 67 if n != name { 68 continue 69 } 70 r.idx[key] = append(r.idx[key][:i], r.idx[key][i+1:]...) 71 break 72 } 73 74 delete(r.names, name) 75 76 if len(r.idx[key]) == 0 { 77 delete(r.idx, key) 78 } 79 } 80 81 // Delete removes all reservations for the passed in key. 82 // All names reserved to this key are released. 83 func (r *Registrar) Delete(key string) { 84 r.mu.Lock() 85 for _, name := range r.idx[key] { 86 delete(r.names, name) 87 } 88 delete(r.idx, key) 89 r.mu.Unlock() 90 } 91 92 // GetNames lists all the reserved names for the given key 93 func (r *Registrar) GetNames(key string) ([]string, error) { 94 r.mu.Lock() 95 defer r.mu.Unlock() 96 97 names, exists := r.idx[key] 98 if !exists { 99 return nil, ErrNoSuchKey 100 } 101 return names, nil 102 } 103 104 // Get returns the key that the passed in name is reserved to 105 func (r *Registrar) Get(name string) (string, error) { 106 r.mu.Lock() 107 key, exists := r.names[name] 108 r.mu.Unlock() 109 110 if !exists { 111 return "", ErrNameNotReserved 112 } 113 return key, nil 114 } 115 116 // GetAll returns all registered names 117 func (r *Registrar) GetAll() map[string][]string { 118 out := make(map[string][]string) 119 120 r.mu.Lock() 121 // copy index into out 122 for id, names := range r.idx { 123 out[id] = names 124 } 125 r.mu.Unlock() 126 return out 127 }