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  }