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  }