sequence.go 9.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336
  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. import (
  6. "fmt"
  7. "github.com/docker/libnetwork/netutils"
  8. )
  9. // Block Sequence constants
  10. // If needed we can think of making these configurable
  11. const (
  12. blockLen = 32
  13. blockBytes = blockLen / 8
  14. blockMAX = 1<<blockLen - 1
  15. blockFirstBit = 1 << (blockLen - 1)
  16. )
  17. // Handle contains the sequece representing the bitmask and its identifier
  18. type Handle struct {
  19. ID string
  20. Head *Sequence
  21. }
  22. // NewHandle returns an instance of the bitmask handler
  23. func NewHandle(id string, numElements uint32) *Handle {
  24. return &Handle{
  25. ID: id,
  26. Head: &Sequence{
  27. Block: 0x0,
  28. Count: getNumBlocks(numElements),
  29. Next: nil,
  30. },
  31. }
  32. }
  33. // Sequence reresents a recurring sequence of 32 bits long bitmasks
  34. type Sequence struct {
  35. Block uint32 // block representing 4 byte long allocation bitmask
  36. Count uint32 // number of consecutive blocks
  37. Next *Sequence // next sequence
  38. }
  39. // NewSequence returns a sequence initialized to represent a bitmaks of numElements bits
  40. func NewSequence(numElements uint32) *Sequence {
  41. return &Sequence{Block: 0x0, Count: getNumBlocks(numElements), Next: nil}
  42. }
  43. // String returns a string representation of the block sequence starting from this block
  44. func (s *Sequence) String() string {
  45. var nextBlock string
  46. if s.Next == nil {
  47. nextBlock = "end"
  48. } else {
  49. nextBlock = s.Next.String()
  50. }
  51. return fmt.Sprintf("(0x%x, %d)->%s", s.Block, s.Count, nextBlock)
  52. }
  53. // GetAvailableBit returns the position of the first unset bit in the bitmask represented by this sequence
  54. func (s *Sequence) GetAvailableBit() (bytePos, bitPos int) {
  55. if s.Block == blockMAX || s.Count == 0 {
  56. return -1, -1
  57. }
  58. bits := 0
  59. bitSel := uint32(blockFirstBit)
  60. for bitSel > 0 && s.Block&bitSel != 0 {
  61. bitSel >>= 1
  62. bits++
  63. }
  64. return bits / 8, bits % 8
  65. }
  66. // Equal checks if this sequence is equal to the passed one
  67. func (s *Sequence) Equal(o *Sequence) bool {
  68. this := s
  69. other := o
  70. for this != nil {
  71. if other == nil {
  72. return false
  73. }
  74. if this.Block != other.Block || this.Count != other.Count {
  75. return false
  76. }
  77. this = this.Next
  78. other = other.Next
  79. }
  80. // Check if other is longer than this
  81. if other != nil {
  82. return false
  83. }
  84. return true
  85. }
  86. // ToByteArray converts the sequence into a byte array
  87. // TODO (aboch): manage network/host order stuff
  88. func (s *Sequence) ToByteArray() ([]byte, error) {
  89. var bb []byte
  90. p := s
  91. for p != nil {
  92. bb = append(bb, netutils.U32ToA(p.Block)...)
  93. bb = append(bb, netutils.U32ToA(p.Count)...)
  94. p = p.Next
  95. }
  96. return bb, nil
  97. }
  98. // FromByteArray construct the sequence from the byte array
  99. // TODO (aboch): manage network/host order stuff
  100. func (s *Sequence) FromByteArray(data []byte) error {
  101. l := len(data)
  102. if l%8 != 0 {
  103. return fmt.Errorf("cannot deserialize byte sequence of lenght %d", l)
  104. }
  105. p := s
  106. i := 0
  107. for {
  108. p.Block = netutils.ATo32(data[i : i+4])
  109. p.Count = netutils.ATo32(data[i+4 : i+8])
  110. i += 8
  111. if i == l {
  112. break
  113. }
  114. p.Next = &Sequence{}
  115. p = p.Next
  116. }
  117. return nil
  118. }
  119. // GetFirstAvailable returns the byte and bit position of the first unset bit
  120. func (h *Handle) GetFirstAvailable() (int, int) {
  121. return GetFirstAvailable(h.Head)
  122. }
  123. // CheckIfAvailable checks if the bit correspondent to the specified ordinal is unset
  124. // If the ordinal is beyond the Sequence limits, a negative response is returned
  125. func (h *Handle) CheckIfAvailable(ordinal int) (int, int) {
  126. return CheckIfAvailable(h.Head, ordinal)
  127. }
  128. // PushReservation pushes the bit reservation inside the bitmask.
  129. func (h *Handle) PushReservation(bytePos, bitPos int, release bool) {
  130. h.Head = PushReservation(bytePos, bitPos, h.Head, release)
  131. }
  132. // GetFirstAvailable looks for the first unset bit in passed mask
  133. func GetFirstAvailable(head *Sequence) (int, int) {
  134. byteIndex := 0
  135. current := head
  136. for current != nil {
  137. if current.Block != blockMAX {
  138. bytePos, bitPos := current.GetAvailableBit()
  139. return byteIndex + bytePos, bitPos
  140. }
  141. byteIndex += int(current.Count * blockBytes)
  142. current = current.Next
  143. }
  144. return -1, -1
  145. }
  146. // CheckIfAvailable checks if the bit correspondent to the specified ordinal is unset
  147. // If the ordinal is beyond the Sequence limits, a negative response is returned
  148. func CheckIfAvailable(head *Sequence, ordinal int) (int, int) {
  149. bytePos := ordinal / 8
  150. bitPos := ordinal % 8
  151. // Find the Sequence containing this byte
  152. current, _, _, inBlockBytePos := findSequence(head, bytePos)
  153. if current != nil {
  154. // Check whether the bit corresponding to the ordinal address is unset
  155. bitSel := uint32(blockFirstBit >> uint(inBlockBytePos*8+bitPos))
  156. if current.Block&bitSel == 0 {
  157. return bytePos, bitPos
  158. }
  159. }
  160. return -1, -1
  161. }
  162. // Given the byte position and the sequences list head, return the pointer to the
  163. // sequence containing the byte (current), the pointer to the previous sequence,
  164. // the number of blocks preceding the block containing the byte inside the current sequence.
  165. // If bytePos is outside of the list, function will return (nil, nil, 0, -1)
  166. func findSequence(head *Sequence, bytePos int) (*Sequence, *Sequence, uint32, int) {
  167. // Find the Sequence containing this byte
  168. previous := head
  169. current := head
  170. n := bytePos
  171. for current.Next != nil && n >= int(current.Count*blockBytes) { // Nil check for less than 32 addresses masks
  172. n -= int(current.Count * blockBytes)
  173. previous = current
  174. current = current.Next
  175. }
  176. // If byte is outside of the list, let caller know
  177. if n >= int(current.Count*blockBytes) {
  178. return nil, nil, 0, -1
  179. }
  180. // Find the byte position inside the block and the number of blocks
  181. // preceding the block containing the byte inside this sequence
  182. precBlocks := uint32(n / blockBytes)
  183. inBlockBytePos := bytePos % blockBytes
  184. return current, previous, precBlocks, inBlockBytePos
  185. }
  186. // PushReservation pushes the bit reservation inside the bitmask.
  187. // Given byte and bit positions, identify the sequence (current) which holds the block containing the affected bit.
  188. // Create a new block with the modified bit according to the operation (allocate/release).
  189. // Create a new Sequence containing the new Block and insert it in the proper position.
  190. // Remove current sequence if empty.
  191. // Check if new Sequence can be merged with neighbour (previous/Next) sequences.
  192. //
  193. //
  194. // Identify "current" Sequence containing block:
  195. // [prev seq] [current seq] [Next seq]
  196. //
  197. // Based on block position, resulting list of sequences can be any of three forms:
  198. //
  199. // Block position Resulting list of sequences
  200. // A) Block is first in current: [prev seq] [new] [modified current seq] [Next seq]
  201. // B) Block is last in current: [prev seq] [modified current seq] [new] [Next seq]
  202. // C) Block is in the middle of current: [prev seq] [curr pre] [new] [curr post] [Next seq]
  203. func PushReservation(bytePos, bitPos int, head *Sequence, release bool) *Sequence {
  204. // Store list's head
  205. newHead := head
  206. // Find the Sequence containing this byte
  207. current, previous, precBlocks, inBlockBytePos := findSequence(head, bytePos)
  208. if current == nil {
  209. return newHead
  210. }
  211. // Construct updated block
  212. bitSel := uint32(blockFirstBit >> uint(inBlockBytePos*8+bitPos))
  213. newBlock := current.Block
  214. if release {
  215. newBlock &^= bitSel
  216. } else {
  217. newBlock |= bitSel
  218. }
  219. // Quit if it was a redundant request
  220. if current.Block == newBlock {
  221. return newHead
  222. }
  223. // Current Sequence inevitably looses one block, upadate Count
  224. current.Count--
  225. // Create new sequence
  226. newSequence := &Sequence{Block: newBlock, Count: 1}
  227. // Insert the new sequence in the list based on block position
  228. if precBlocks == 0 { // First in sequence (A)
  229. newSequence.Next = current
  230. if current == head {
  231. newHead = newSequence
  232. previous = newHead
  233. } else {
  234. previous.Next = newSequence
  235. }
  236. removeCurrentIfEmpty(&newHead, newSequence, current)
  237. mergeSequences(previous)
  238. } else if precBlocks == current.Count-2 { // Last in sequence (B)
  239. newSequence.Next = current.Next
  240. current.Next = newSequence
  241. mergeSequences(current)
  242. } else { // In between the sequence (C)
  243. currPre := &Sequence{Block: current.Block, Count: precBlocks, Next: newSequence}
  244. currPost := current
  245. currPost.Count -= precBlocks
  246. newSequence.Next = currPost
  247. if currPost == head {
  248. newHead = currPre
  249. } else {
  250. previous.Next = currPre
  251. }
  252. // No merging or empty current possible here
  253. }
  254. return newHead
  255. }
  256. // Removes the current sequence from the list if empty, adjusting the head pointer if needed
  257. func removeCurrentIfEmpty(head **Sequence, previous, current *Sequence) {
  258. if current.Count == 0 {
  259. if current == *head {
  260. *head = current.Next
  261. } else {
  262. previous.Next = current.Next
  263. current = current.Next
  264. }
  265. }
  266. }
  267. // Given a pointer to a Sequence, it checks if it can be merged with any following sequences
  268. // It stops when no more merging is possible.
  269. // TODO: Optimization: only attempt merge from start to end sequence, no need to scan till the end of the list
  270. func mergeSequences(seq *Sequence) {
  271. if seq != nil {
  272. // Merge all what possible from seq
  273. for seq.Next != nil && seq.Block == seq.Next.Block {
  274. seq.Count += seq.Next.Count
  275. seq.Next = seq.Next.Next
  276. }
  277. // Move to Next
  278. mergeSequences(seq.Next)
  279. }
  280. }
  281. // Serialize converts the sequence into a byte array
  282. func Serialize(head *Sequence) ([]byte, error) {
  283. return nil, nil
  284. }
  285. // Deserialize decodes the byte array into a sequence
  286. func Deserialize(data []byte) (*Sequence, error) {
  287. return nil, nil
  288. }
  289. func getNumBlocks(numBits uint32) uint32 {
  290. numBlocks := numBits / blockLen
  291. if numBits%blockLen != 0 {
  292. numBlocks++
  293. }
  294. return numBlocks
  295. }