github.com/Heebron/moby@v0.0.0-20221111184709-6eab4f55faf7/libnetwork/idm/idm.go (about) 1 // Package idm manages reservation/release of numerical ids from a configured set of contiguous ids 2 package idm 3 4 import ( 5 "errors" 6 "fmt" 7 8 "github.com/docker/docker/libnetwork/bitseq" 9 "github.com/docker/docker/libnetwork/datastore" 10 ) 11 12 // Idm manages the reservation/release of numerical ids from a contiguous set 13 type Idm struct { 14 start uint64 15 end uint64 16 handle *bitseq.Handle 17 } 18 19 // New returns an instance of id manager for a [start,end] set of numerical ids 20 func New(ds datastore.DataStore, id string, start, end uint64) (*Idm, error) { 21 if id == "" { 22 return nil, errors.New("Invalid id") 23 } 24 if end <= start { 25 return nil, fmt.Errorf("Invalid set range: [%d, %d]", start, end) 26 } 27 28 h, err := bitseq.NewHandle("idm", ds, id, 1+end-start) 29 if err != nil { 30 return nil, fmt.Errorf("failed to initialize bit sequence handler: %s", err.Error()) 31 } 32 33 return &Idm{start: start, end: end, handle: h}, nil 34 } 35 36 // GetID returns the first available id in the set 37 func (i *Idm) GetID(serial bool) (uint64, error) { 38 if i.handle == nil { 39 return 0, errors.New("ID set is not initialized") 40 } 41 ordinal, err := i.handle.SetAny(serial) 42 return i.start + ordinal, err 43 } 44 45 // GetSpecificID tries to reserve the specified id 46 func (i *Idm) GetSpecificID(id uint64) error { 47 if i.handle == nil { 48 return errors.New("ID set is not initialized") 49 } 50 51 if id < i.start || id > i.end { 52 return errors.New("Requested id does not belong to the set") 53 } 54 55 return i.handle.Set(id - i.start) 56 } 57 58 // GetIDInRange returns the first available id in the set within a [start,end] range 59 func (i *Idm) GetIDInRange(start, end uint64, serial bool) (uint64, error) { 60 if i.handle == nil { 61 return 0, errors.New("ID set is not initialized") 62 } 63 64 if start < i.start || end > i.end { 65 return 0, errors.New("Requested range does not belong to the set") 66 } 67 68 ordinal, err := i.handle.SetAnyInRange(start-i.start, end-i.start, serial) 69 70 return i.start + ordinal, err 71 } 72 73 // Release releases the specified id 74 func (i *Idm) Release(id uint64) { 75 i.handle.Unset(id - i.start) 76 }