sequence.go 6.5 KB

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