sequence.go 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213
  1. // Package bitseq provides a structure and utilities for representing a long
  2. // bitmask which is persisted in a datastore. It is backed by [bitmap.Bitmap]
  3. // which operates directly on the encoded representation, without uncompressing.
  4. package bitseq
  5. import (
  6. "encoding/json"
  7. "fmt"
  8. "sync"
  9. "github.com/docker/docker/libnetwork/bitmap"
  10. "github.com/docker/docker/libnetwork/datastore"
  11. "github.com/docker/docker/libnetwork/types"
  12. )
  13. var (
  14. // ErrNoBitAvailable is returned when no more bits are available to set
  15. ErrNoBitAvailable = bitmap.ErrNoBitAvailable
  16. // ErrBitAllocated is returned when the specific bit requested is already set
  17. ErrBitAllocated = bitmap.ErrBitAllocated
  18. )
  19. // Handle contains the sequence representing the bitmask and its identifier
  20. type Handle struct {
  21. app string
  22. id string
  23. dbIndex uint64
  24. dbExists bool
  25. store datastore.DataStore
  26. bm *bitmap.Bitmap
  27. mu sync.Mutex
  28. }
  29. // NewHandle returns a thread-safe instance of the bitmask handler
  30. func NewHandle(app string, ds datastore.DataStore, id string, numElements uint64) (*Handle, error) {
  31. h := &Handle{
  32. bm: bitmap.New(numElements),
  33. app: app,
  34. id: id,
  35. store: ds,
  36. }
  37. if h.store == nil {
  38. return h, nil
  39. }
  40. // Get the initial status from the ds if present.
  41. if err := h.store.GetObject(datastore.Key(h.Key()...), h); err != nil && err != datastore.ErrKeyNotFound {
  42. return nil, err
  43. }
  44. // If the handle is not in store, write it.
  45. if !h.Exists() {
  46. if err := h.writeToStore(); err != nil {
  47. return nil, fmt.Errorf("failed to write bitsequence to store: %v", err)
  48. }
  49. }
  50. return h, nil
  51. }
  52. func (h *Handle) getCopy() *Handle {
  53. return &Handle{
  54. bm: bitmap.Copy(h.bm),
  55. app: h.app,
  56. id: h.id,
  57. dbIndex: h.dbIndex,
  58. dbExists: h.dbExists,
  59. store: h.store,
  60. }
  61. }
  62. // SetAnyInRange atomically sets the first unset bit in the specified range in the sequence and returns the corresponding ordinal
  63. func (h *Handle) SetAnyInRange(start, end uint64, serial bool) (uint64, error) {
  64. return h.apply(func(b *bitmap.Bitmap) (uint64, error) { return b.SetAnyInRange(start, end, serial) })
  65. }
  66. // SetAny atomically sets the first unset bit in the sequence and returns the corresponding ordinal
  67. func (h *Handle) SetAny(serial bool) (uint64, error) {
  68. return h.apply(func(b *bitmap.Bitmap) (uint64, error) { return b.SetAny(serial) })
  69. }
  70. // Set atomically sets the corresponding bit in the sequence
  71. func (h *Handle) Set(ordinal uint64) error {
  72. _, err := h.apply(func(b *bitmap.Bitmap) (uint64, error) { return 0, b.Set(ordinal) })
  73. return err
  74. }
  75. // Unset atomically unsets the corresponding bit in the sequence
  76. func (h *Handle) Unset(ordinal uint64) error {
  77. _, err := h.apply(func(b *bitmap.Bitmap) (uint64, error) { return 0, b.Unset(ordinal) })
  78. return err
  79. }
  80. // IsSet atomically checks if the ordinal bit is set. In case ordinal
  81. // is outside of the bit sequence limits, false is returned.
  82. func (h *Handle) IsSet(ordinal uint64) bool {
  83. h.mu.Lock()
  84. defer h.mu.Unlock()
  85. return h.bm.IsSet(ordinal)
  86. }
  87. // set/reset the bit
  88. func (h *Handle) apply(op func(*bitmap.Bitmap) (uint64, error)) (uint64, error) {
  89. for {
  90. var store datastore.DataStore
  91. h.mu.Lock()
  92. store = h.store
  93. if store != nil {
  94. h.mu.Unlock() // The lock is acquired in the GetObject
  95. if err := store.GetObject(datastore.Key(h.Key()...), h); err != nil && err != datastore.ErrKeyNotFound {
  96. return 0, err
  97. }
  98. h.mu.Lock() // Acquire the lock back
  99. }
  100. // Create a private copy of h and work on it
  101. nh := h.getCopy()
  102. ret, err := op(nh.bm)
  103. if err != nil {
  104. h.mu.Unlock()
  105. return ret, err
  106. }
  107. if h.store != nil {
  108. h.mu.Unlock()
  109. // Attempt to write private copy to store
  110. if err := nh.writeToStore(); err != nil {
  111. if _, ok := err.(types.RetryError); !ok {
  112. return ret, fmt.Errorf("internal failure while setting the bit: %v", err)
  113. }
  114. // Retry
  115. continue
  116. }
  117. h.mu.Lock()
  118. }
  119. // Previous atomic push was successful. Save private copy to local copy
  120. h.bm = nh.bm
  121. h.dbExists = nh.dbExists
  122. h.dbIndex = nh.dbIndex
  123. h.mu.Unlock()
  124. return ret, nil
  125. }
  126. }
  127. // Destroy removes from the datastore the data belonging to this handle
  128. func (h *Handle) Destroy() error {
  129. for {
  130. if err := h.deleteFromStore(); err != nil {
  131. if _, ok := err.(types.RetryError); !ok {
  132. return fmt.Errorf("internal failure while destroying the sequence: %v", err)
  133. }
  134. // Fetch latest
  135. if err := h.store.GetObject(datastore.Key(h.Key()...), h); err != nil {
  136. if err == datastore.ErrKeyNotFound { // already removed
  137. return nil
  138. }
  139. return fmt.Errorf("failed to fetch from store when destroying the sequence: %v", err)
  140. }
  141. continue
  142. }
  143. return nil
  144. }
  145. }
  146. // Bits returns the length of the bit sequence
  147. func (h *Handle) Bits() uint64 {
  148. h.mu.Lock()
  149. defer h.mu.Unlock()
  150. return h.bm.Bits()
  151. }
  152. // Unselected returns the number of bits which are not selected
  153. func (h *Handle) Unselected() uint64 {
  154. h.mu.Lock()
  155. defer h.mu.Unlock()
  156. return h.bm.Unselected()
  157. }
  158. func (h *Handle) String() string {
  159. h.mu.Lock()
  160. defer h.mu.Unlock()
  161. return fmt.Sprintf("App: %s, ID: %s, DBIndex: 0x%x, %s",
  162. h.app, h.id, h.dbIndex, h.bm)
  163. }
  164. type jsonMessage struct {
  165. ID string `json:"id"`
  166. Sequence *bitmap.Bitmap `json:"sequence"`
  167. }
  168. // MarshalJSON encodes h into a JSON message.
  169. func (h *Handle) MarshalJSON() ([]byte, error) {
  170. h.mu.Lock()
  171. defer h.mu.Unlock()
  172. m := jsonMessage{ID: h.id, Sequence: h.bm}
  173. return json.Marshal(m)
  174. }
  175. // UnmarshalJSON decodes a JSON message into h.
  176. func (h *Handle) UnmarshalJSON(data []byte) error {
  177. var m jsonMessage
  178. if err := json.Unmarshal(data, &m); err != nil {
  179. return err
  180. }
  181. h.mu.Lock()
  182. defer h.mu.Unlock()
  183. h.id, h.bm = m.ID, m.Sequence
  184. return nil
  185. }