github.com/zhuohuang-hust/src-cbuild@v0.0.0-20230105071821-c7aab3e7c840/mergeCode/libnetwork/bitseq/sequence.go (about) 1 // Package bitseq provides a structure and utilities for representing long bitmask 2 // as sequence of run-lenght encoded blocks. It operates direclty on the encoded 3 // representation, it does not decode/encode. 4 package bitseq 5 6 import ( 7 "encoding/binary" 8 "encoding/json" 9 "fmt" 10 "sync" 11 12 log "github.com/Sirupsen/logrus" 13 "github.com/docker/libnetwork/datastore" 14 "github.com/docker/libnetwork/types" 15 ) 16 17 // block sequence constants 18 // If needed we can think of making these configurable 19 const ( 20 blockLen = uint32(32) 21 blockBytes = uint64(blockLen / 8) 22 blockMAX = uint32(1<<blockLen - 1) 23 blockFirstBit = uint32(1) << (blockLen - 1) 24 invalidPos = uint64(0xFFFFFFFFFFFFFFFF) 25 ) 26 27 var ( 28 // ErrNoBitAvailable is returned when no more bits are available to set 29 ErrNoBitAvailable = fmt.Errorf("no bit available") 30 // ErrBitAllocated is returned when the specific bit requested is already set 31 ErrBitAllocated = fmt.Errorf("requested bit is already allocated") 32 ) 33 34 // Handle contains the sequece representing the bitmask and its identifier 35 type Handle struct { 36 bits uint64 37 unselected uint64 38 head *sequence 39 app string 40 id string 41 dbIndex uint64 42 dbExists bool 43 store datastore.DataStore 44 sync.Mutex 45 } 46 47 // NewHandle returns a thread-safe instance of the bitmask handler 48 func NewHandle(app string, ds datastore.DataStore, id string, numElements uint64) (*Handle, error) { 49 h := &Handle{ 50 app: app, 51 id: id, 52 store: ds, 53 bits: numElements, 54 unselected: numElements, 55 head: &sequence{ 56 block: 0x0, 57 count: getNumBlocks(numElements), 58 }, 59 } 60 61 if h.store == nil { 62 return h, nil 63 } 64 65 // Get the initial status from the ds if present. 66 if err := h.store.GetObject(datastore.Key(h.Key()...), h); err != nil && err != datastore.ErrKeyNotFound { 67 return nil, err 68 } 69 70 // If the handle is not in store, write it. 71 if !h.Exists() { 72 if err := h.writeToStore(); err != nil { 73 return nil, fmt.Errorf("failed to write bitsequence to store: %v", err) 74 } 75 } 76 77 return h, nil 78 } 79 80 // sequence represents a recurring sequence of 32 bits long bitmasks 81 type sequence struct { 82 block uint32 // block is a symbol representing 4 byte long allocation bitmask 83 count uint64 // number of consecutive blocks (symbols) 84 next *sequence // next sequence 85 } 86 87 // String returns a string representation of the block sequence starting from this block 88 func (s *sequence) toString() string { 89 var nextBlock string 90 if s.next == nil { 91 nextBlock = "end" 92 } else { 93 nextBlock = s.next.toString() 94 } 95 return fmt.Sprintf("(0x%x, %d)->%s", s.block, s.count, nextBlock) 96 } 97 98 // GetAvailableBit returns the position of the first unset bit in the bitmask represented by this sequence 99 func (s *sequence) getAvailableBit(from uint64) (uint64, uint64, error) { 100 if s.block == blockMAX || s.count == 0 { 101 return invalidPos, invalidPos, ErrNoBitAvailable 102 } 103 bits := from 104 bitSel := blockFirstBit >> from 105 for bitSel > 0 && s.block&bitSel != 0 { 106 bitSel >>= 1 107 bits++ 108 } 109 return bits / 8, bits % 8, nil 110 } 111 112 // GetCopy returns a copy of the linked list rooted at this node 113 func (s *sequence) getCopy() *sequence { 114 n := &sequence{block: s.block, count: s.count} 115 pn := n 116 ps := s.next 117 for ps != nil { 118 pn.next = &sequence{block: ps.block, count: ps.count} 119 pn = pn.next 120 ps = ps.next 121 } 122 return n 123 } 124 125 // Equal checks if this sequence is equal to the passed one 126 func (s *sequence) equal(o *sequence) bool { 127 this := s 128 other := o 129 for this != nil { 130 if other == nil { 131 return false 132 } 133 if this.block != other.block || this.count != other.count { 134 return false 135 } 136 this = this.next 137 other = other.next 138 } 139 // Check if other is longer than this 140 if other != nil { 141 return false 142 } 143 return true 144 } 145 146 // ToByteArray converts the sequence into a byte array 147 func (s *sequence) toByteArray() ([]byte, error) { 148 var bb []byte 149 150 p := s 151 for p != nil { 152 b := make([]byte, 12) 153 binary.BigEndian.PutUint32(b[0:], p.block) 154 binary.BigEndian.PutUint64(b[4:], p.count) 155 bb = append(bb, b...) 156 p = p.next 157 } 158 159 return bb, nil 160 } 161 162 // fromByteArray construct the sequence from the byte array 163 func (s *sequence) fromByteArray(data []byte) error { 164 l := len(data) 165 if l%12 != 0 { 166 return fmt.Errorf("cannot deserialize byte sequence of length %d (%v)", l, data) 167 } 168 169 p := s 170 i := 0 171 for { 172 p.block = binary.BigEndian.Uint32(data[i : i+4]) 173 p.count = binary.BigEndian.Uint64(data[i+4 : i+12]) 174 i += 12 175 if i == l { 176 break 177 } 178 p.next = &sequence{} 179 p = p.next 180 } 181 182 return nil 183 } 184 185 func (h *Handle) getCopy() *Handle { 186 return &Handle{ 187 bits: h.bits, 188 unselected: h.unselected, 189 head: h.head.getCopy(), 190 app: h.app, 191 id: h.id, 192 dbIndex: h.dbIndex, 193 dbExists: h.dbExists, 194 store: h.store, 195 } 196 } 197 198 // SetAnyInRange atomically sets the first unset bit in the specified range in the sequence and returns the corresponding ordinal 199 func (h *Handle) SetAnyInRange(start, end uint64) (uint64, error) { 200 if end < start || end >= h.bits { 201 return invalidPos, fmt.Errorf("invalid bit range [%d, %d]", start, end) 202 } 203 if h.Unselected() == 0 { 204 return invalidPos, ErrNoBitAvailable 205 } 206 return h.set(0, start, end, true, false) 207 } 208 209 // SetAny atomically sets the first unset bit in the sequence and returns the corresponding ordinal 210 func (h *Handle) SetAny() (uint64, error) { 211 if h.Unselected() == 0 { 212 return invalidPos, ErrNoBitAvailable 213 } 214 return h.set(0, 0, h.bits-1, true, false) 215 } 216 217 // Set atomically sets the corresponding bit in the sequence 218 func (h *Handle) Set(ordinal uint64) error { 219 if err := h.validateOrdinal(ordinal); err != nil { 220 return err 221 } 222 _, err := h.set(ordinal, 0, 0, false, false) 223 return err 224 } 225 226 // Unset atomically unsets the corresponding bit in the sequence 227 func (h *Handle) Unset(ordinal uint64) error { 228 if err := h.validateOrdinal(ordinal); err != nil { 229 return err 230 } 231 _, err := h.set(ordinal, 0, 0, false, true) 232 return err 233 } 234 235 // IsSet atomically checks if the ordinal bit is set. In case ordinal 236 // is outside of the bit sequence limits, false is returned. 237 func (h *Handle) IsSet(ordinal uint64) bool { 238 if err := h.validateOrdinal(ordinal); err != nil { 239 return false 240 } 241 h.Lock() 242 _, _, err := checkIfAvailable(h.head, ordinal) 243 h.Unlock() 244 return err != nil 245 } 246 247 func (h *Handle) runConsistencyCheck() bool { 248 corrupted := false 249 for p, c := h.head, h.head.next; c != nil; c = c.next { 250 if c.count == 0 { 251 corrupted = true 252 p.next = c.next 253 continue // keep same p 254 } 255 p = c 256 } 257 return corrupted 258 } 259 260 // CheckConsistency checks if the bit sequence is in an inconsistent state and attempts to fix it. 261 // It looks for a corruption signature that may happen in docker 1.9.0 and 1.9.1. 262 func (h *Handle) CheckConsistency() error { 263 for { 264 h.Lock() 265 store := h.store 266 h.Unlock() 267 268 if store != nil { 269 if err := store.GetObject(datastore.Key(h.Key()...), h); err != nil && err != datastore.ErrKeyNotFound { 270 return err 271 } 272 } 273 274 h.Lock() 275 nh := h.getCopy() 276 h.Unlock() 277 278 if !nh.runConsistencyCheck() { 279 return nil 280 } 281 282 if err := nh.writeToStore(); err != nil { 283 if _, ok := err.(types.RetryError); !ok { 284 return fmt.Errorf("internal failure while fixing inconsistent bitsequence: %v", err) 285 } 286 continue 287 } 288 289 log.Infof("Fixed inconsistent bit sequence in datastore:\n%s\n%s", h, nh) 290 291 h.Lock() 292 h.head = nh.head 293 h.Unlock() 294 295 return nil 296 } 297 } 298 299 // set/reset the bit 300 func (h *Handle) set(ordinal, start, end uint64, any bool, release bool) (uint64, error) { 301 var ( 302 bitPos uint64 303 bytePos uint64 304 ret uint64 305 err error 306 ) 307 308 for { 309 var store datastore.DataStore 310 h.Lock() 311 store = h.store 312 h.Unlock() 313 if store != nil { 314 if err := store.GetObject(datastore.Key(h.Key()...), h); err != nil && err != datastore.ErrKeyNotFound { 315 return ret, err 316 } 317 } 318 319 h.Lock() 320 // Get position if available 321 if release { 322 bytePos, bitPos = ordinalToPos(ordinal) 323 } else { 324 if any { 325 bytePos, bitPos, err = getFirstAvailable(h.head, start) 326 ret = posToOrdinal(bytePos, bitPos) 327 if end < ret { 328 err = ErrNoBitAvailable 329 } 330 } else { 331 bytePos, bitPos, err = checkIfAvailable(h.head, ordinal) 332 ret = ordinal 333 } 334 } 335 if err != nil { 336 h.Unlock() 337 return ret, err 338 } 339 340 // Create a private copy of h and work on it 341 nh := h.getCopy() 342 h.Unlock() 343 344 nh.head = pushReservation(bytePos, bitPos, nh.head, release) 345 if release { 346 nh.unselected++ 347 } else { 348 nh.unselected-- 349 } 350 351 // Attempt to write private copy to store 352 if err := nh.writeToStore(); err != nil { 353 if _, ok := err.(types.RetryError); !ok { 354 return ret, fmt.Errorf("internal failure while setting the bit: %v", err) 355 } 356 // Retry 357 continue 358 } 359 360 // Previous atomic push was succesfull. Save private copy to local copy 361 h.Lock() 362 defer h.Unlock() 363 h.unselected = nh.unselected 364 h.head = nh.head 365 h.dbExists = nh.dbExists 366 h.dbIndex = nh.dbIndex 367 return ret, nil 368 } 369 } 370 371 // checks is needed because to cover the case where the number of bits is not a multiple of blockLen 372 func (h *Handle) validateOrdinal(ordinal uint64) error { 373 h.Lock() 374 defer h.Unlock() 375 if ordinal >= h.bits { 376 return fmt.Errorf("bit does not belong to the sequence") 377 } 378 return nil 379 } 380 381 // Destroy removes from the datastore the data belonging to this handle 382 func (h *Handle) Destroy() error { 383 for { 384 if err := h.deleteFromStore(); err != nil { 385 if _, ok := err.(types.RetryError); !ok { 386 return fmt.Errorf("internal failure while destroying the sequence: %v", err) 387 } 388 // Fetch latest 389 if err := h.store.GetObject(datastore.Key(h.Key()...), h); err != nil { 390 if err == datastore.ErrKeyNotFound { // already removed 391 return nil 392 } 393 return fmt.Errorf("failed to fetch from store when destroying the sequence: %v", err) 394 } 395 continue 396 } 397 return nil 398 } 399 } 400 401 // ToByteArray converts this handle's data into a byte array 402 func (h *Handle) ToByteArray() ([]byte, error) { 403 404 h.Lock() 405 defer h.Unlock() 406 ba := make([]byte, 16) 407 binary.BigEndian.PutUint64(ba[0:], h.bits) 408 binary.BigEndian.PutUint64(ba[8:], h.unselected) 409 bm, err := h.head.toByteArray() 410 if err != nil { 411 return nil, fmt.Errorf("failed to serialize head: %s", err.Error()) 412 } 413 ba = append(ba, bm...) 414 415 return ba, nil 416 } 417 418 // FromByteArray reads his handle's data from a byte array 419 func (h *Handle) FromByteArray(ba []byte) error { 420 if ba == nil { 421 return fmt.Errorf("nil byte array") 422 } 423 424 nh := &sequence{} 425 err := nh.fromByteArray(ba[16:]) 426 if err != nil { 427 return fmt.Errorf("failed to deserialize head: %s", err.Error()) 428 } 429 430 h.Lock() 431 h.head = nh 432 h.bits = binary.BigEndian.Uint64(ba[0:8]) 433 h.unselected = binary.BigEndian.Uint64(ba[8:16]) 434 h.Unlock() 435 436 return nil 437 } 438 439 // Bits returns the length of the bit sequence 440 func (h *Handle) Bits() uint64 { 441 return h.bits 442 } 443 444 // Unselected returns the number of bits which are not selected 445 func (h *Handle) Unselected() uint64 { 446 h.Lock() 447 defer h.Unlock() 448 return h.unselected 449 } 450 451 func (h *Handle) String() string { 452 h.Lock() 453 defer h.Unlock() 454 return fmt.Sprintf("App: %s, ID: %s, DBIndex: 0x%x, bits: %d, unselected: %d, sequence: %s", 455 h.app, h.id, h.dbIndex, h.bits, h.unselected, h.head.toString()) 456 } 457 458 // MarshalJSON encodes Handle into json message 459 func (h *Handle) MarshalJSON() ([]byte, error) { 460 m := map[string]interface{}{ 461 "id": h.id, 462 } 463 464 b, err := h.ToByteArray() 465 if err != nil { 466 return nil, err 467 } 468 m["sequence"] = b 469 return json.Marshal(m) 470 } 471 472 // UnmarshalJSON decodes json message into Handle 473 func (h *Handle) UnmarshalJSON(data []byte) error { 474 var ( 475 m map[string]interface{} 476 b []byte 477 err error 478 ) 479 if err = json.Unmarshal(data, &m); err != nil { 480 return err 481 } 482 h.id = m["id"].(string) 483 bi, _ := json.Marshal(m["sequence"]) 484 if err := json.Unmarshal(bi, &b); err != nil { 485 return err 486 } 487 return h.FromByteArray(b) 488 } 489 490 // getFirstAvailable looks for the first unset bit in passed mask starting from start 491 func getFirstAvailable(head *sequence, start uint64) (uint64, uint64, error) { 492 // Find sequence which contains the start bit 493 byteStart, bitStart := ordinalToPos(start) 494 current, _, _, inBlockBytePos := findSequence(head, byteStart) 495 496 // Derive the this sequence offsets 497 byteOffset := byteStart - inBlockBytePos 498 bitOffset := inBlockBytePos*8 + bitStart 499 500 for current != nil { 501 if current.block != blockMAX { 502 bytePos, bitPos, err := current.getAvailableBit(bitOffset) 503 return byteOffset + bytePos, bitPos, err 504 } 505 // Moving to next block: Reset bit offset. 506 bitOffset = 0 507 byteOffset += current.count * blockBytes 508 current = current.next 509 } 510 return invalidPos, invalidPos, ErrNoBitAvailable 511 } 512 513 // checkIfAvailable checks if the bit correspondent to the specified ordinal is unset 514 // If the ordinal is beyond the sequence limits, a negative response is returned 515 func checkIfAvailable(head *sequence, ordinal uint64) (uint64, uint64, error) { 516 bytePos, bitPos := ordinalToPos(ordinal) 517 518 // Find the sequence containing this byte 519 current, _, _, inBlockBytePos := findSequence(head, bytePos) 520 if current != nil { 521 // Check whether the bit corresponding to the ordinal address is unset 522 bitSel := blockFirstBit >> (inBlockBytePos*8 + bitPos) 523 if current.block&bitSel == 0 { 524 return bytePos, bitPos, nil 525 } 526 } 527 528 return invalidPos, invalidPos, ErrBitAllocated 529 } 530 531 // Given the byte position and the sequences list head, return the pointer to the 532 // sequence containing the byte (current), the pointer to the previous sequence, 533 // the number of blocks preceding the block containing the byte inside the current sequence. 534 // If bytePos is outside of the list, function will return (nil, nil, 0, invalidPos) 535 func findSequence(head *sequence, bytePos uint64) (*sequence, *sequence, uint64, uint64) { 536 // Find the sequence containing this byte 537 previous := head 538 current := head 539 n := bytePos 540 for current.next != nil && n >= (current.count*blockBytes) { // Nil check for less than 32 addresses masks 541 n -= (current.count * blockBytes) 542 previous = current 543 current = current.next 544 } 545 546 // If byte is outside of the list, let caller know 547 if n >= (current.count * blockBytes) { 548 return nil, nil, 0, invalidPos 549 } 550 551 // Find the byte position inside the block and the number of blocks 552 // preceding the block containing the byte inside this sequence 553 precBlocks := n / blockBytes 554 inBlockBytePos := bytePos % blockBytes 555 556 return current, previous, precBlocks, inBlockBytePos 557 } 558 559 // PushReservation pushes the bit reservation inside the bitmask. 560 // Given byte and bit positions, identify the sequence (current) which holds the block containing the affected bit. 561 // Create a new block with the modified bit according to the operation (allocate/release). 562 // Create a new sequence containing the new block and insert it in the proper position. 563 // Remove current sequence if empty. 564 // Check if new sequence can be merged with neighbour (previous/next) sequences. 565 // 566 // 567 // Identify "current" sequence containing block: 568 // [prev seq] [current seq] [next seq] 569 // 570 // Based on block position, resulting list of sequences can be any of three forms: 571 // 572 // block position Resulting list of sequences 573 // A) block is first in current: [prev seq] [new] [modified current seq] [next seq] 574 // B) block is last in current: [prev seq] [modified current seq] [new] [next seq] 575 // C) block is in the middle of current: [prev seq] [curr pre] [new] [curr post] [next seq] 576 func pushReservation(bytePos, bitPos uint64, head *sequence, release bool) *sequence { 577 // Store list's head 578 newHead := head 579 580 // Find the sequence containing this byte 581 current, previous, precBlocks, inBlockBytePos := findSequence(head, bytePos) 582 if current == nil { 583 return newHead 584 } 585 586 // Construct updated block 587 bitSel := blockFirstBit >> (inBlockBytePos*8 + bitPos) 588 newBlock := current.block 589 if release { 590 newBlock &^= bitSel 591 } else { 592 newBlock |= bitSel 593 } 594 595 // Quit if it was a redundant request 596 if current.block == newBlock { 597 return newHead 598 } 599 600 // Current sequence inevitably looses one block, upadate count 601 current.count-- 602 603 // Create new sequence 604 newSequence := &sequence{block: newBlock, count: 1} 605 606 // Insert the new sequence in the list based on block position 607 if precBlocks == 0 { // First in sequence (A) 608 newSequence.next = current 609 if current == head { 610 newHead = newSequence 611 previous = newHead 612 } else { 613 previous.next = newSequence 614 } 615 removeCurrentIfEmpty(&newHead, newSequence, current) 616 mergeSequences(previous) 617 } else if precBlocks == current.count { // Last in sequence (B) 618 newSequence.next = current.next 619 current.next = newSequence 620 mergeSequences(current) 621 } else { // In between the sequence (C) 622 currPre := &sequence{block: current.block, count: precBlocks, next: newSequence} 623 currPost := current 624 currPost.count -= precBlocks 625 newSequence.next = currPost 626 if currPost == head { 627 newHead = currPre 628 } else { 629 previous.next = currPre 630 } 631 // No merging or empty current possible here 632 } 633 634 return newHead 635 } 636 637 // Removes the current sequence from the list if empty, adjusting the head pointer if needed 638 func removeCurrentIfEmpty(head **sequence, previous, current *sequence) { 639 if current.count == 0 { 640 if current == *head { 641 *head = current.next 642 } else { 643 previous.next = current.next 644 current = current.next 645 } 646 } 647 } 648 649 // Given a pointer to a sequence, it checks if it can be merged with any following sequences 650 // It stops when no more merging is possible. 651 // TODO: Optimization: only attempt merge from start to end sequence, no need to scan till the end of the list 652 func mergeSequences(seq *sequence) { 653 if seq != nil { 654 // Merge all what possible from seq 655 for seq.next != nil && seq.block == seq.next.block { 656 seq.count += seq.next.count 657 seq.next = seq.next.next 658 } 659 // Move to next 660 mergeSequences(seq.next) 661 } 662 } 663 664 func getNumBlocks(numBits uint64) uint64 { 665 numBlocks := numBits / uint64(blockLen) 666 if numBits%uint64(blockLen) != 0 { 667 numBlocks++ 668 } 669 return numBlocks 670 } 671 672 func ordinalToPos(ordinal uint64) (uint64, uint64) { 673 return ordinal / 8, ordinal % 8 674 } 675 676 func posToOrdinal(bytePos, bitPos uint64) uint64 { 677 return bytePos*8 + bitPos 678 }