bitseq to provide handle
- Handle contains sequence and identifier. This way datastore integration can be done at bitseq level. Signed-off-by: Alessandro Boch <aboch@docker.com>
This commit is contained in:
parent
3ff75bd42d
commit
1f76a79bf7
|
@ -18,6 +18,24 @@ const (
|
|||
blockFirstBit = 1 << (blockLen - 1)
|
||||
)
|
||||
|
||||
// Handle contains the sequece representing the bitmask and its identifier
|
||||
type Handle struct {
|
||||
ID string
|
||||
Head *Sequence
|
||||
}
|
||||
|
||||
// NewHandle returns an instance of the bitmask handler
|
||||
func NewHandle(id string, numElements uint32) *Handle {
|
||||
return &Handle{
|
||||
ID: id,
|
||||
Head: &Sequence{
|
||||
Block: 0x0,
|
||||
Count: getNumBlocks(numElements),
|
||||
Next: nil,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
// Sequence reresents a recurring sequence of 32 bits long bitmasks
|
||||
type Sequence struct {
|
||||
Block uint32 // block representing 4 byte long allocation bitmask
|
||||
|
@ -25,8 +43,8 @@ type Sequence struct {
|
|||
Next *Sequence // next sequence
|
||||
}
|
||||
|
||||
// New returns a sequence initialized to represent a bitmaks of numElements bits
|
||||
func New(numElements uint32) *Sequence {
|
||||
// NewSequence returns a sequence initialized to represent a bitmaks of numElements bits
|
||||
func NewSequence(numElements uint32) *Sequence {
|
||||
return &Sequence{Block: 0x0, Count: getNumBlocks(numElements), Next: nil}
|
||||
}
|
||||
|
||||
|
@ -115,6 +133,22 @@ func (s *Sequence) FromByteArray(data []byte) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
// GetFirstAvailable returns the byte and bit position of the first unset bit
|
||||
func (h *Handle) GetFirstAvailable() (int, int) {
|
||||
return GetFirstAvailable(h.Head)
|
||||
}
|
||||
|
||||
// CheckIfAvailable checks if the bit correspondent to the specified ordinal is unset
|
||||
// If the ordinal is beyond the Sequence limits, a negative response is returned
|
||||
func (h *Handle) CheckIfAvailable(ordinal int) (int, int) {
|
||||
return CheckIfAvailable(h.Head, ordinal)
|
||||
}
|
||||
|
||||
// PushReservation pushes the bit reservation inside the bitmask.
|
||||
func (h *Handle) PushReservation(bytePos, bitPos int, release bool) {
|
||||
h.Head = PushReservation(bytePos, bitPos, h.Head, release)
|
||||
}
|
||||
|
||||
// GetFirstAvailable looks for the first unset bit in passed mask
|
||||
func GetFirstAvailable(head *Sequence) (int, int) {
|
||||
byteIndex := 0
|
||||
|
|
|
@ -52,7 +52,7 @@ func (s *subnetKey) String() string {
|
|||
// The bitmask is stored a run-length encoded seq.Sequence of 4 bytes blcoks.
|
||||
type bitmask struct {
|
||||
subnet *net.IPNet
|
||||
addressMask *bitseq.Sequence
|
||||
addressMask *bitseq.Handle
|
||||
freeAddresses int
|
||||
}
|
||||
|
||||
|
@ -102,7 +102,7 @@ func (a *Allocator) AddSubnet(addrSpace AddressSpace, subnetInfo *SubnetInfo) er
|
|||
a.Lock()
|
||||
a.addresses[smallKey] = &bitmask{
|
||||
subnet: sub,
|
||||
addressMask: bitseq.New(uint32(numAddresses)),
|
||||
addressMask: bitseq.NewHandle(smallKey.String(), uint32(numAddresses)),
|
||||
freeAddresses: numAddresses,
|
||||
}
|
||||
a.Unlock()
|
||||
|
@ -293,7 +293,7 @@ func (a *Allocator) Release(addrSpace AddressSpace, address net.IP) {
|
|||
space := a.addresses[subnetKey{addrSpace, sub.String()}]
|
||||
ordinal := ipToInt(getHostPortionIP(address, space.subnet))
|
||||
// Release it
|
||||
space.addressMask = bitseq.PushReservation(ordinal/8, ordinal%8, space.addressMask, true)
|
||||
space.addressMask.PushReservation(ordinal/8, ordinal%8, true)
|
||||
space.freeAddresses++
|
||||
return
|
||||
}
|
||||
|
@ -362,17 +362,17 @@ again:
|
|||
return nil, ErrNoAvailableIPs
|
||||
}
|
||||
if prefAddress == nil {
|
||||
bytePos, bitPos = bitseq.GetFirstAvailable(smallSubnet.addressMask)
|
||||
bytePos, bitPos = smallSubnet.addressMask.GetFirstAvailable()
|
||||
} else {
|
||||
ordinal := ipToInt(getHostPortionIP(prefAddress, smallSubnet.subnet))
|
||||
bytePos, bitPos = bitseq.CheckIfAvailable(smallSubnet.addressMask, ordinal)
|
||||
bytePos, bitPos = smallSubnet.addressMask.CheckIfAvailable(ordinal)
|
||||
}
|
||||
if bytePos == -1 {
|
||||
return nil, ErrNoAvailableIPs
|
||||
}
|
||||
|
||||
// Lock it
|
||||
smallSubnet.addressMask = bitseq.PushReservation(bytePos, bitPos, smallSubnet.addressMask, false)
|
||||
smallSubnet.addressMask.PushReservation(bytePos, bitPos, false)
|
||||
smallSubnet.freeAddresses--
|
||||
|
||||
// Build IP ordinal
|
||||
|
|
|
@ -462,10 +462,10 @@ func assertGetAddress(t *testing.T, subnet string) {
|
|||
|
||||
bm := &bitmask{
|
||||
subnet: sub,
|
||||
addressMask: bitseq.New(uint32(numAddresses)),
|
||||
addressMask: bitseq.NewHandle("default/192.168.0.0/24", uint32(numAddresses)),
|
||||
freeAddresses: numAddresses,
|
||||
}
|
||||
numBlocks := bm.addressMask.Count
|
||||
numBlocks := bm.addressMask.Head.Count
|
||||
|
||||
start := time.Now()
|
||||
run := 0
|
||||
|
@ -476,9 +476,9 @@ func assertGetAddress(t *testing.T, subnet string) {
|
|||
if printTime {
|
||||
fmt.Printf("\nTaken %v, to allocate all addresses on %s. (nemAddresses: %d. Runs: %d)", time.Since(start), subnet, numAddresses, run)
|
||||
}
|
||||
if bm.addressMask.Block != expectedMax || bm.addressMask.Count != numBlocks {
|
||||
if bm.addressMask.Head.Block != expectedMax || bm.addressMask.Head.Count != numBlocks {
|
||||
t.Fatalf("Failed to effectively reserve all addresses on %s. Expected (0x%x, %d) as first sequence. Found (0x%x,%d)",
|
||||
subnet, expectedMax, numBlocks, bm.addressMask.Block, bm.addressMask.Count)
|
||||
subnet, expectedMax, numBlocks, bm.addressMask.Head.Block, bm.addressMask.Head.Count)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue