Skip to content

Commit

Permalink
Fixing issue with bit allocation byteoffset calculation
Browse files Browse the repository at this point in the history
The byteoffset calculation was skewed to double include
the offset value calculated. The double calculation
happens if the starting ordinal is part of the head
sequence block. This error in calculation could result
in duplicate but getting allocated eventually propogating
to ipam and vni id allocations

Signed-off-by: Abhinandan Prativadi <abhi@docker.com>
  • Loading branch information
abhi committed Jun 9, 2017
1 parent 8b46b24 commit 6180b85
Show file tree
Hide file tree
Showing 2 changed files with 11 additions and 5 deletions.
15 changes: 10 additions & 5 deletions bitseq/sequence.go
Original file line number Diff line number Diff line change
Expand Up @@ -350,7 +350,6 @@ func (h *Handle) set(ordinal, start, end uint64, any bool, release bool) (uint64
} else {
nh.unselected--
}

// Attempt to write private copy to store
if err := nh.writeToStore(); err != nil {
if _, ok := err.(types.RetryError); !ok {
Expand Down Expand Up @@ -492,30 +491,35 @@ func (h *Handle) UnmarshalJSON(data []byte) error {

// getFirstAvailable looks for the first unset bit in passed mask starting from start
func getFirstAvailable(head *sequence, start uint64) (uint64, uint64, error) {

// Find sequence which contains the start bit
byteStart, bitStart := ordinalToPos(start)
current, _, _, inBlockBytePos := findSequence(head, byteStart)

// Derive the this sequence offsets
byteOffset := byteStart - inBlockBytePos
bitOffset := inBlockBytePos*8 + bitStart

var firstOffset uint64
if current == head {
firstOffset = byteOffset
}
for current != nil {
if current.block != blockMAX {
bytePos, bitPos, err := current.getAvailableBit(bitOffset)
return byteOffset + bytePos, bitPos, err
}
// Moving to next block: Reset bit offset.
bitOffset = 0
byteOffset += current.count * blockBytes
byteOffset += (current.count * blockBytes) - firstOffset
firstOffset = 0
current = current.next
}
return invalidPos, invalidPos, ErrNoBitAvailable
}

//getAvailableFromCurrent will look for available ordinal from the current ordinal.
// getAvailableFromCurrent will look for available ordinal from the current ordinal.
// If none found then it will loop back to the start to check of the available bit.
//This can be further optimized to check from start till curr in case of a rollover
// This can be further optimized to check from start till curr in case of a rollover
func getAvailableFromCurrent(head *sequence, start, curr, end uint64) (uint64, uint64, error) {
var bytePos, bitPos uint64
if curr != 0 && curr > start {
Expand All @@ -524,6 +528,7 @@ func getAvailableFromCurrent(head *sequence, start, curr, end uint64) (uint64, u
if end < ret {
goto begin
}

return bytePos, bitPos, nil
}

Expand Down
1 change: 1 addition & 0 deletions bitseq/store.go
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,7 @@ func (h *Handle) CopyTo(o datastore.KVObject) error {
dstH.dbIndex = h.dbIndex
dstH.dbExists = h.dbExists
dstH.store = h.store
dstH.curr = h.curr
dstH.Unlock()

return nil
Expand Down

0 comments on commit 6180b85

Please sign in to comment.