github.com/Prakhar-Agarwal-byte/moby@v0.0.0-20231027092010-a14e3e8ab87e/libnetwork/bitmap/sequence.go (about) 1 // Package bitmap provides a datatype for long vectors of bits. 2 package bitmap 3 4 import ( 5 "encoding/binary" 6 "encoding/json" 7 "errors" 8 "fmt" 9 ) 10 11 // block sequence constants 12 // If needed we can think of making these configurable 13 const ( 14 blockLen = uint32(32) 15 blockBytes = uint64(blockLen / 8) 16 blockMAX = uint32(1<<blockLen - 1) 17 blockFirstBit = uint32(1) << (blockLen - 1) 18 invalidPos = uint64(0xFFFFFFFFFFFFFFFF) 19 ) 20 21 var ( 22 // ErrNoBitAvailable is returned when no more bits are available to set 23 ErrNoBitAvailable = errors.New("no bit available") 24 // ErrBitAllocated is returned when the specific bit requested is already set 25 ErrBitAllocated = errors.New("requested bit is already allocated") 26 ) 27 28 // https://github.com/golang/go/issues/8005#issuecomment-190753527 29 type noCopy struct{} 30 31 func (noCopy) Lock() {} 32 33 // Bitmap is a fixed-length bit vector. It is not safe for concurrent use. 34 // 35 // The data is stored as a list of run-length encoded blocks. It operates 36 // directly on the encoded representation, without decompressing. 37 type Bitmap struct { 38 bits uint64 39 unselected uint64 40 head *sequence 41 curr uint64 42 43 // Shallow copies would share the same head pointer but a copy of the 44 // unselected count. Mutating the sequence through one would change the 45 // bits for all copies but only update that one copy's unselected count, 46 // which would result in subtle bugs. 47 noCopy noCopy 48 } 49 50 // NewHandle returns a new Bitmap of ordinals in the interval [0, n). 51 func New(n uint64) *Bitmap { 52 return &Bitmap{ 53 bits: n, 54 unselected: n, 55 head: &sequence{ 56 block: 0x0, 57 count: getNumBlocks(n), 58 }, 59 } 60 } 61 62 // Copy returns a deep copy of b. 63 func Copy(b *Bitmap) *Bitmap { 64 return &Bitmap{ 65 bits: b.bits, 66 unselected: b.unselected, 67 head: b.head.getCopy(), 68 curr: b.curr, 69 } 70 } 71 72 // sequence represents a recurring sequence of 32 bits long bitmasks 73 type sequence struct { 74 block uint32 // block is a symbol representing 4 byte long allocation bitmask 75 count uint64 // number of consecutive blocks (symbols) 76 next *sequence // next sequence 77 } 78 79 // String returns a string representation of the block sequence starting from this block 80 func (s *sequence) toString() string { 81 var nextBlock string 82 if s.next == nil { 83 nextBlock = "end" 84 } else { 85 nextBlock = s.next.toString() 86 } 87 return fmt.Sprintf("(0x%x, %d)->%s", s.block, s.count, nextBlock) 88 } 89 90 // GetAvailableBit returns the position of the first unset bit in the bitmask represented by this sequence 91 func (s *sequence) getAvailableBit(from uint64) (uint64, uint64, error) { 92 if s.block == blockMAX || s.count == 0 { 93 return invalidPos, invalidPos, ErrNoBitAvailable 94 } 95 bits := from 96 bitSel := blockFirstBit >> from 97 for bitSel > 0 && s.block&bitSel != 0 { 98 bitSel >>= 1 99 bits++ 100 } 101 // Check if the loop exited because it could not 102 // find any available bit int block starting from 103 // "from". Return invalid pos in that case. 104 if bitSel == 0 { 105 return invalidPos, invalidPos, ErrNoBitAvailable 106 } 107 return bits / 8, bits % 8, nil 108 } 109 110 // GetCopy returns a copy of the linked list rooted at this node 111 func (s *sequence) getCopy() *sequence { 112 n := &sequence{block: s.block, count: s.count} 113 pn := n 114 ps := s.next 115 for ps != nil { 116 pn.next = &sequence{block: ps.block, count: ps.count} 117 pn = pn.next 118 ps = ps.next 119 } 120 return n 121 } 122 123 // Equal checks if this sequence is equal to the passed one 124 func (s *sequence) equal(o *sequence) bool { 125 this := s 126 other := o 127 for this != nil { 128 if other == nil { 129 return false 130 } 131 if this.block != other.block || this.count != other.count { 132 return false 133 } 134 this = this.next 135 other = other.next 136 } 137 return other == nil 138 } 139 140 // ToByteArray converts the sequence into a byte array 141 func (s *sequence) toByteArray() ([]byte, error) { 142 var bb []byte 143 144 p := s 145 b := make([]byte, 12) 146 for p != nil { 147 binary.BigEndian.PutUint32(b[0:], p.block) 148 binary.BigEndian.PutUint64(b[4:], p.count) 149 bb = append(bb, b...) 150 p = p.next 151 } 152 153 return bb, nil 154 } 155 156 // fromByteArray construct the sequence from the byte array 157 func (s *sequence) fromByteArray(data []byte) error { 158 l := len(data) 159 if l%12 != 0 { 160 return fmt.Errorf("cannot deserialize byte sequence of length %d (%v)", l, data) 161 } 162 163 p := s 164 i := 0 165 for { 166 p.block = binary.BigEndian.Uint32(data[i : i+4]) 167 p.count = binary.BigEndian.Uint64(data[i+4 : i+12]) 168 i += 12 169 if i == l { 170 break 171 } 172 p.next = &sequence{} 173 p = p.next 174 } 175 176 return nil 177 } 178 179 // SetAnyInRange sets the first unset bit in the range [start, end] and returns 180 // the ordinal of the set bit. 181 // 182 // When serial=true, the bitmap is scanned starting from the ordinal following 183 // the bit most recently set by [Bitmap.SetAny] or [Bitmap.SetAnyInRange]. 184 func (h *Bitmap) SetAnyInRange(start, end uint64, serial bool) (uint64, error) { 185 if end < start || end >= h.bits { 186 return invalidPos, fmt.Errorf("invalid bit range [%d, %d)", start, end) 187 } 188 if h.Unselected() == 0 { 189 return invalidPos, ErrNoBitAvailable 190 } 191 return h.set(0, start, end, true, false, serial) 192 } 193 194 // SetAny sets the first unset bit in the sequence and returns the ordinal of 195 // the set bit. 196 // 197 // When serial=true, the bitmap is scanned starting from the ordinal following 198 // the bit most recently set by [Bitmap.SetAny] or [Bitmap.SetAnyInRange]. 199 func (h *Bitmap) SetAny(serial bool) (uint64, error) { 200 if h.Unselected() == 0 { 201 return invalidPos, ErrNoBitAvailable 202 } 203 return h.set(0, 0, h.bits-1, true, false, serial) 204 } 205 206 // Set atomically sets the corresponding bit in the sequence 207 func (h *Bitmap) Set(ordinal uint64) error { 208 if err := h.validateOrdinal(ordinal); err != nil { 209 return err 210 } 211 _, err := h.set(ordinal, 0, 0, false, false, false) 212 return err 213 } 214 215 // Unset atomically unsets the corresponding bit in the sequence 216 func (h *Bitmap) Unset(ordinal uint64) error { 217 if err := h.validateOrdinal(ordinal); err != nil { 218 return err 219 } 220 _, err := h.set(ordinal, 0, 0, false, true, false) 221 return err 222 } 223 224 // IsSet atomically checks if the ordinal bit is set. In case ordinal 225 // is outside of the bit sequence limits, false is returned. 226 func (h *Bitmap) IsSet(ordinal uint64) bool { 227 if err := h.validateOrdinal(ordinal); err != nil { 228 return false 229 } 230 _, _, err := checkIfAvailable(h.head, ordinal) 231 return err != nil 232 } 233 234 // set/reset the bit 235 func (h *Bitmap) set(ordinal, start, end uint64, any bool, release bool, serial bool) (uint64, error) { 236 var ( 237 bitPos uint64 238 bytePos uint64 239 ret uint64 240 err error 241 ) 242 243 curr := uint64(0) 244 if serial { 245 curr = h.curr 246 } 247 // Get position if available 248 if release { 249 bytePos, bitPos = ordinalToPos(ordinal) 250 } else { 251 if any { 252 bytePos, bitPos, err = getAvailableFromCurrent(h.head, start, curr, end) 253 ret = posToOrdinal(bytePos, bitPos) 254 if err == nil { 255 h.curr = ret + 1 256 } 257 } else { 258 bytePos, bitPos, err = checkIfAvailable(h.head, ordinal) 259 ret = ordinal 260 } 261 } 262 if err != nil { 263 return ret, err 264 } 265 266 h.head = pushReservation(bytePos, bitPos, h.head, release) 267 if release { 268 h.unselected++ 269 } else { 270 h.unselected-- 271 } 272 273 return ret, nil 274 } 275 276 // checks is needed because to cover the case where the number of bits is not a multiple of blockLen 277 func (h *Bitmap) validateOrdinal(ordinal uint64) error { 278 if ordinal >= h.bits { 279 return errors.New("bit does not belong to the sequence") 280 } 281 return nil 282 } 283 284 // MarshalBinary encodes h into a binary representation. 285 func (h *Bitmap) MarshalBinary() ([]byte, error) { 286 ba := make([]byte, 16) 287 binary.BigEndian.PutUint64(ba[0:], h.bits) 288 binary.BigEndian.PutUint64(ba[8:], h.unselected) 289 bm, err := h.head.toByteArray() 290 if err != nil { 291 return nil, fmt.Errorf("failed to serialize head: %v", err) 292 } 293 ba = append(ba, bm...) 294 295 return ba, nil 296 } 297 298 // UnmarshalBinary decodes a binary representation of a Bitmap value which was 299 // generated using [Bitmap.MarshalBinary]. 300 // 301 // The scan position for serial [Bitmap.SetAny] and [Bitmap.SetAnyInRange] 302 // operations is neither unmarshaled nor reset. 303 func (h *Bitmap) UnmarshalBinary(ba []byte) error { 304 if ba == nil { 305 return errors.New("nil byte array") 306 } 307 308 nh := &sequence{} 309 err := nh.fromByteArray(ba[16:]) 310 if err != nil { 311 return fmt.Errorf("failed to deserialize head: %v", err) 312 } 313 314 h.head = nh 315 h.bits = binary.BigEndian.Uint64(ba[0:8]) 316 h.unselected = binary.BigEndian.Uint64(ba[8:16]) 317 return nil 318 } 319 320 // Bits returns the length of the bit sequence 321 func (h *Bitmap) Bits() uint64 { 322 return h.bits 323 } 324 325 // Unselected returns the number of bits which are not selected 326 func (h *Bitmap) Unselected() uint64 { 327 return h.unselected 328 } 329 330 func (h *Bitmap) String() string { 331 return fmt.Sprintf("Bits: %d, Unselected: %d, Sequence: %s Curr:%d", 332 h.bits, h.unselected, h.head.toString(), h.curr) 333 } 334 335 // MarshalJSON encodes h into a JSON message 336 func (h *Bitmap) MarshalJSON() ([]byte, error) { 337 b, err := h.MarshalBinary() 338 if err != nil { 339 return nil, err 340 } 341 return json.Marshal(b) 342 } 343 344 // UnmarshalJSON decodes JSON message into h 345 func (h *Bitmap) UnmarshalJSON(data []byte) error { 346 var b []byte 347 if err := json.Unmarshal(data, &b); err != nil { 348 return err 349 } 350 return h.UnmarshalBinary(b) 351 } 352 353 // getFirstAvailable looks for the first unset bit in passed mask starting from start 354 func getFirstAvailable(head *sequence, start uint64) (uint64, uint64, error) { 355 // Find sequence which contains the start bit 356 byteStart, bitStart := ordinalToPos(start) 357 current, _, precBlocks, inBlockBytePos := findSequence(head, byteStart) 358 // Derive the this sequence offsets 359 byteOffset := byteStart - inBlockBytePos 360 bitOffset := inBlockBytePos*8 + bitStart 361 for current != nil { 362 if current.block != blockMAX { 363 // If the current block is not full, check if there is any bit 364 // from the current bit in the current block. If not, before proceeding to the 365 // next block node, make sure we check for available bit in the next 366 // instance of the same block. Due to RLE same block signature will be 367 // compressed. 368 retry: 369 bytePos, bitPos, err := current.getAvailableBit(bitOffset) 370 if err != nil && precBlocks == current.count-1 { 371 // This is the last instance in the same block node, 372 // so move to the next block. 373 goto next 374 } 375 if err != nil { 376 // There are some more instances of the same block, so add the offset 377 // and be optimistic that you will find the available bit in the next 378 // instance of the same block. 379 bitOffset = 0 380 byteOffset += blockBytes 381 precBlocks++ 382 goto retry 383 } 384 return byteOffset + bytePos, bitPos, err 385 } 386 // Moving to next block: Reset bit offset. 387 next: 388 bitOffset = 0 389 byteOffset += (current.count * blockBytes) - (precBlocks * blockBytes) 390 precBlocks = 0 391 current = current.next 392 } 393 return invalidPos, invalidPos, ErrNoBitAvailable 394 } 395 396 // getAvailableFromCurrent will look for available ordinal from the current ordinal. 397 // If none found then it will loop back to the start to check of the available bit. 398 // This can be further optimized to check from start till curr in case of a rollover 399 func getAvailableFromCurrent(head *sequence, start, curr, end uint64) (uint64, uint64, error) { 400 var bytePos, bitPos uint64 401 var err error 402 if curr != 0 && curr > start { 403 bytePos, bitPos, err = getFirstAvailable(head, curr) 404 ret := posToOrdinal(bytePos, bitPos) 405 if end < ret || err != nil { 406 goto begin 407 } 408 return bytePos, bitPos, nil 409 } 410 411 begin: 412 bytePos, bitPos, err = getFirstAvailable(head, start) 413 ret := posToOrdinal(bytePos, bitPos) 414 if end < ret || err != nil { 415 return invalidPos, invalidPos, ErrNoBitAvailable 416 } 417 return bytePos, bitPos, nil 418 } 419 420 // checkIfAvailable checks if the bit correspondent to the specified ordinal is unset 421 // If the ordinal is beyond the sequence limits, a negative response is returned 422 func checkIfAvailable(head *sequence, ordinal uint64) (uint64, uint64, error) { 423 bytePos, bitPos := ordinalToPos(ordinal) 424 425 // Find the sequence containing this byte 426 current, _, _, inBlockBytePos := findSequence(head, bytePos) 427 if current != nil { 428 // Check whether the bit corresponding to the ordinal address is unset 429 bitSel := blockFirstBit >> (inBlockBytePos*8 + bitPos) 430 if current.block&bitSel == 0 { 431 return bytePos, bitPos, nil 432 } 433 } 434 435 return invalidPos, invalidPos, ErrBitAllocated 436 } 437 438 // Given the byte position and the sequences list head, return the pointer to the 439 // sequence containing the byte (current), the pointer to the previous sequence, 440 // the number of blocks preceding the block containing the byte inside the current sequence. 441 // If bytePos is outside of the list, function will return (nil, nil, 0, invalidPos) 442 func findSequence(head *sequence, bytePos uint64) (*sequence, *sequence, uint64, uint64) { 443 // Find the sequence containing this byte 444 previous := head 445 current := head 446 n := bytePos 447 for current.next != nil && n >= (current.count*blockBytes) { // Nil check for less than 32 addresses masks 448 n -= (current.count * blockBytes) 449 previous = current 450 current = current.next 451 } 452 453 // If byte is outside of the list, let caller know 454 if n >= (current.count * blockBytes) { 455 return nil, nil, 0, invalidPos 456 } 457 458 // Find the byte position inside the block and the number of blocks 459 // preceding the block containing the byte inside this sequence 460 precBlocks := n / blockBytes 461 inBlockBytePos := bytePos % blockBytes 462 463 return current, previous, precBlocks, inBlockBytePos 464 } 465 466 // PushReservation pushes the bit reservation inside the bitmask. 467 // Given byte and bit positions, identify the sequence (current) which holds the block containing the affected bit. 468 // Create a new block with the modified bit according to the operation (allocate/release). 469 // Create a new sequence containing the new block and insert it in the proper position. 470 // Remove current sequence if empty. 471 // Check if new sequence can be merged with neighbour (previous/next) sequences. 472 // 473 // Identify "current" sequence containing block: 474 // 475 // [prev seq] [current seq] [next seq] 476 // 477 // Based on block position, resulting list of sequences can be any of three forms: 478 // 479 // block position Resulting list of sequences 480 // 481 // A) block is first in current: [prev seq] [new] [modified current seq] [next seq] 482 // B) block is last in current: [prev seq] [modified current seq] [new] [next seq] 483 // C) block is in the middle of current: [prev seq] [curr pre] [new] [curr post] [next seq] 484 func pushReservation(bytePos, bitPos uint64, head *sequence, release bool) *sequence { 485 // Store list's head 486 newHead := head 487 488 // Find the sequence containing this byte 489 current, previous, precBlocks, inBlockBytePos := findSequence(head, bytePos) 490 if current == nil { 491 return newHead 492 } 493 494 // Construct updated block 495 bitSel := blockFirstBit >> (inBlockBytePos*8 + bitPos) 496 newBlock := current.block 497 if release { 498 newBlock &^= bitSel 499 } else { 500 newBlock |= bitSel 501 } 502 503 // Quit if it was a redundant request 504 if current.block == newBlock { 505 return newHead 506 } 507 508 // Current sequence inevitably looses one block, upadate count 509 current.count-- 510 511 // Create new sequence 512 newSequence := &sequence{block: newBlock, count: 1} 513 514 // Insert the new sequence in the list based on block position 515 if precBlocks == 0 { // First in sequence (A) 516 newSequence.next = current 517 if current == head { 518 newHead = newSequence 519 previous = newHead 520 } else { 521 previous.next = newSequence 522 } 523 removeCurrentIfEmpty(&newHead, newSequence, current) 524 mergeSequences(previous) 525 } else if precBlocks == current.count { // Last in sequence (B) 526 newSequence.next = current.next 527 current.next = newSequence 528 mergeSequences(current) 529 } else { // In between the sequence (C) 530 currPre := &sequence{block: current.block, count: precBlocks, next: newSequence} 531 currPost := current 532 currPost.count -= precBlocks 533 newSequence.next = currPost 534 if currPost == head { 535 newHead = currPre 536 } else { 537 previous.next = currPre 538 } 539 // No merging or empty current possible here 540 } 541 542 return newHead 543 } 544 545 // Removes the current sequence from the list if empty, adjusting the head pointer if needed 546 func removeCurrentIfEmpty(head **sequence, previous, current *sequence) { 547 if current.count == 0 { 548 if current == *head { 549 *head = current.next 550 } else { 551 previous.next = current.next 552 } 553 } 554 } 555 556 // Given a pointer to a sequence, it checks if it can be merged with any following sequences 557 // It stops when no more merging is possible. 558 // TODO: Optimization: only attempt merge from start to end sequence, no need to scan till the end of the list 559 func mergeSequences(seq *sequence) { 560 if seq != nil { 561 // Merge all what possible from seq 562 for seq.next != nil && seq.block == seq.next.block { 563 seq.count += seq.next.count 564 seq.next = seq.next.next 565 } 566 // Move to next 567 mergeSequences(seq.next) 568 } 569 } 570 571 func getNumBlocks(numBits uint64) uint64 { 572 numBlocks := numBits / uint64(blockLen) 573 if numBits%uint64(blockLen) != 0 { 574 numBlocks++ 575 } 576 return numBlocks 577 } 578 579 func ordinalToPos(ordinal uint64) (uint64, uint64) { 580 return ordinal / 8, ordinal % 8 581 } 582 583 func posToOrdinal(bytePos, bitPos uint64) uint64 { 584 return bytePos*8 + bitPos 585 }