You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

259 lines
5.7 KiB

more solid weed mount (#4089) * compare chunks by timestamp * fix slab clearing error * fix test compilation * move oldest chunk to sealed, instead of by fullness * lock on fh.entryViewCache * remove verbose logs * revert slat clearing * less logs * less logs * track write and read by timestamp * remove useless logic * add entry lock on file handle release * use mem chunk only, swap file chunk has problems * comment out code that maybe used later * add debug mode to compare data read and write * more efficient readResolvedChunks with linked list * small optimization * fix test compilation * minor fix on writer * add SeparateGarbageChunks * group chunks into sections * turn off debug mode * fix tests * fix tests * tmp enable swap file chunk * Revert "tmp enable swap file chunk" This reverts commit 985137ec472924e4815f258189f6ca9f2168a0a7. * simple refactoring * simple refactoring * do not re-use swap file chunk. Sealed chunks should not be re-used. * comment out debugging facilities * either mem chunk or swap file chunk is fine now * remove orderedMutex as *semaphore.Weighted not found impactful * optimize size calculation for changing large files * optimize performance to avoid going through the long list of chunks * still problems with swap file chunk * rename * tiny optimization * swap file chunk save only successfully read data * fix * enable both mem and swap file chunk * resolve chunks with range * rename * fix chunk interval list * also change file handle chunk group when adding chunks * pick in-active chunk with time-decayed counter * fix compilation * avoid nil with empty fh.entry * refactoring * rename * rename * refactor visible intervals to *list.List * refactor chunkViews to *list.List * add IntervalList for generic interval list * change visible interval to use IntervalList in generics * cahnge chunkViews to *IntervalList[*ChunkView] * use NewFileChunkSection to create * rename variables * refactor * fix renaming leftover * renaming * renaming * add insert interval * interval list adds lock * incrementally add chunks to readers Fixes: 1. set start and stop offset for the value object 2. clone the value object 3. use pointer instead of copy-by-value when passing to interval.Value 4. use insert interval since adding chunk could be out of order * fix tests compilation * fix tests compilation
2 years ago
more solid weed mount (#4089) * compare chunks by timestamp * fix slab clearing error * fix test compilation * move oldest chunk to sealed, instead of by fullness * lock on fh.entryViewCache * remove verbose logs * revert slat clearing * less logs * less logs * track write and read by timestamp * remove useless logic * add entry lock on file handle release * use mem chunk only, swap file chunk has problems * comment out code that maybe used later * add debug mode to compare data read and write * more efficient readResolvedChunks with linked list * small optimization * fix test compilation * minor fix on writer * add SeparateGarbageChunks * group chunks into sections * turn off debug mode * fix tests * fix tests * tmp enable swap file chunk * Revert "tmp enable swap file chunk" This reverts commit 985137ec472924e4815f258189f6ca9f2168a0a7. * simple refactoring * simple refactoring * do not re-use swap file chunk. Sealed chunks should not be re-used. * comment out debugging facilities * either mem chunk or swap file chunk is fine now * remove orderedMutex as *semaphore.Weighted not found impactful * optimize size calculation for changing large files * optimize performance to avoid going through the long list of chunks * still problems with swap file chunk * rename * tiny optimization * swap file chunk save only successfully read data * fix * enable both mem and swap file chunk * resolve chunks with range * rename * fix chunk interval list * also change file handle chunk group when adding chunks * pick in-active chunk with time-decayed counter * fix compilation * avoid nil with empty fh.entry * refactoring * rename * rename * refactor visible intervals to *list.List * refactor chunkViews to *list.List * add IntervalList for generic interval list * change visible interval to use IntervalList in generics * cahnge chunkViews to *IntervalList[*ChunkView] * use NewFileChunkSection to create * rename variables * refactor * fix renaming leftover * renaming * renaming * add insert interval * interval list adds lock * incrementally add chunks to readers Fixes: 1. set start and stop offset for the value object 2. clone the value object 3. use pointer instead of copy-by-value when passing to interval.Value 4. use insert interval since adding chunk could be out of order * fix tests compilation * fix tests compilation
2 years ago
more solid weed mount (#4089) * compare chunks by timestamp * fix slab clearing error * fix test compilation * move oldest chunk to sealed, instead of by fullness * lock on fh.entryViewCache * remove verbose logs * revert slat clearing * less logs * less logs * track write and read by timestamp * remove useless logic * add entry lock on file handle release * use mem chunk only, swap file chunk has problems * comment out code that maybe used later * add debug mode to compare data read and write * more efficient readResolvedChunks with linked list * small optimization * fix test compilation * minor fix on writer * add SeparateGarbageChunks * group chunks into sections * turn off debug mode * fix tests * fix tests * tmp enable swap file chunk * Revert "tmp enable swap file chunk" This reverts commit 985137ec472924e4815f258189f6ca9f2168a0a7. * simple refactoring * simple refactoring * do not re-use swap file chunk. Sealed chunks should not be re-used. * comment out debugging facilities * either mem chunk or swap file chunk is fine now * remove orderedMutex as *semaphore.Weighted not found impactful * optimize size calculation for changing large files * optimize performance to avoid going through the long list of chunks * still problems with swap file chunk * rename * tiny optimization * swap file chunk save only successfully read data * fix * enable both mem and swap file chunk * resolve chunks with range * rename * fix chunk interval list * also change file handle chunk group when adding chunks * pick in-active chunk with time-decayed counter * fix compilation * avoid nil with empty fh.entry * refactoring * rename * rename * refactor visible intervals to *list.List * refactor chunkViews to *list.List * add IntervalList for generic interval list * change visible interval to use IntervalList in generics * cahnge chunkViews to *IntervalList[*ChunkView] * use NewFileChunkSection to create * rename variables * refactor * fix renaming leftover * renaming * renaming * add insert interval * interval list adds lock * incrementally add chunks to readers Fixes: 1. set start and stop offset for the value object 2. clone the value object 3. use pointer instead of copy-by-value when passing to interval.Value 4. use insert interval since adding chunk could be out of order * fix tests compilation * fix tests compilation
2 years ago
  1. package filer
  2. import (
  3. "math"
  4. "sync"
  5. )
  6. type IntervalValue interface {
  7. SetStartStop(start, stop int64)
  8. Clone() IntervalValue
  9. }
  10. type Interval[T IntervalValue] struct {
  11. StartOffset int64
  12. StopOffset int64
  13. TsNs int64
  14. Value T
  15. Prev *Interval[T]
  16. Next *Interval[T]
  17. }
  18. func (interval *Interval[T]) Size() int64 {
  19. return interval.StopOffset - interval.StartOffset
  20. }
  21. // IntervalList mark written intervals within one page chunk
  22. type IntervalList[T IntervalValue] struct {
  23. head *Interval[T]
  24. tail *Interval[T]
  25. Lock sync.RWMutex
  26. }
  27. func NewIntervalList[T IntervalValue]() *IntervalList[T] {
  28. list := &IntervalList[T]{
  29. head: &Interval[T]{
  30. StartOffset: -1,
  31. StopOffset: -1,
  32. },
  33. tail: &Interval[T]{
  34. StartOffset: math.MaxInt64,
  35. StopOffset: math.MaxInt64,
  36. },
  37. }
  38. return list
  39. }
  40. func (list *IntervalList[T]) Front() (interval *Interval[T]) {
  41. return list.head.Next
  42. }
  43. func (list *IntervalList[T]) AppendInterval(interval *Interval[T]) {
  44. list.Lock.Lock()
  45. defer list.Lock.Unlock()
  46. if list.head.Next == nil {
  47. list.head.Next = interval
  48. }
  49. interval.Prev = list.tail.Prev
  50. if list.tail.Prev != nil {
  51. list.tail.Prev.Next = interval
  52. }
  53. list.tail.Prev = interval
  54. }
  55. func (list *IntervalList[T]) Overlay(startOffset, stopOffset, tsNs int64, value T) {
  56. if startOffset >= stopOffset {
  57. return
  58. }
  59. interval := &Interval[T]{
  60. StartOffset: startOffset,
  61. StopOffset: stopOffset,
  62. TsNs: tsNs,
  63. Value: value,
  64. }
  65. list.Lock.Lock()
  66. defer list.Lock.Unlock()
  67. list.overlayInterval(interval)
  68. }
  69. func (list *IntervalList[T]) InsertInterval(startOffset, stopOffset, tsNs int64, value T) {
  70. interval := &Interval[T]{
  71. StartOffset: startOffset,
  72. StopOffset: stopOffset,
  73. TsNs: tsNs,
  74. Value: value,
  75. }
  76. list.Lock.Lock()
  77. defer list.Lock.Unlock()
  78. value.SetStartStop(startOffset, stopOffset)
  79. list.insertInterval(interval)
  80. }
  81. func (list *IntervalList[T]) insertInterval(interval *Interval[T]) {
  82. prev := list.head
  83. next := prev.Next
  84. for interval.StartOffset < interval.StopOffset {
  85. if next == nil {
  86. // add to the end
  87. list.insertBetween(prev, interval, list.tail)
  88. break
  89. }
  90. // interval is ahead of the next
  91. if interval.StopOffset <= next.StartOffset {
  92. list.insertBetween(prev, interval, next)
  93. break
  94. }
  95. // interval is after the next
  96. if next.StopOffset <= interval.StartOffset {
  97. prev = next
  98. next = next.Next
  99. continue
  100. }
  101. // intersecting next and interval
  102. if interval.TsNs >= next.TsNs {
  103. // interval is newer
  104. if next.StartOffset < interval.StartOffset {
  105. // left side of next is ahead of interval
  106. t := &Interval[T]{
  107. StartOffset: next.StartOffset,
  108. StopOffset: interval.StartOffset,
  109. TsNs: next.TsNs,
  110. Value: next.Value.Clone().(T),
  111. }
  112. t.Value.SetStartStop(t.StartOffset, t.StopOffset)
  113. list.insertBetween(prev, t, interval)
  114. next.StartOffset = interval.StartOffset
  115. next.Value.SetStartStop(next.StartOffset, next.StopOffset)
  116. prev = t
  117. }
  118. if interval.StopOffset < next.StopOffset {
  119. // right side of next is after interval
  120. next.StartOffset = interval.StopOffset
  121. next.Value.SetStartStop(next.StartOffset, next.StopOffset)
  122. list.insertBetween(prev, interval, next)
  123. break
  124. } else {
  125. // next is covered
  126. prev.Next = interval
  127. next = next.Next
  128. }
  129. } else {
  130. // next is newer
  131. if interval.StartOffset < next.StartOffset {
  132. // left side of interval is ahead of next
  133. t := &Interval[T]{
  134. StartOffset: interval.StartOffset,
  135. StopOffset: next.StartOffset,
  136. TsNs: interval.TsNs,
  137. Value: interval.Value.Clone().(T),
  138. }
  139. t.Value.SetStartStop(t.StartOffset, t.StopOffset)
  140. list.insertBetween(prev, t, next)
  141. interval.StartOffset = next.StartOffset
  142. interval.Value.SetStartStop(interval.StartOffset, interval.StopOffset)
  143. }
  144. if next.StopOffset < interval.StopOffset {
  145. // right side of interval is after next
  146. interval.StartOffset = next.StopOffset
  147. interval.Value.SetStartStop(interval.StartOffset, interval.StopOffset)
  148. } else {
  149. // interval is covered
  150. break
  151. }
  152. }
  153. }
  154. }
  155. func (list *IntervalList[T]) insertBetween(a, interval, b *Interval[T]) {
  156. a.Next = interval
  157. b.Prev = interval
  158. if a != list.head {
  159. interval.Prev = a
  160. }
  161. if b != list.tail {
  162. interval.Next = b
  163. }
  164. }
  165. func (list *IntervalList[T]) overlayInterval(interval *Interval[T]) {
  166. //t := list.head
  167. //for ; t.Next != nil; t = t.Next {
  168. // if t.TsNs > interval.TsNs {
  169. // println("writes is out of order", t.TsNs-interval.TsNs, "ns")
  170. // }
  171. //}
  172. p := list.head
  173. for ; p.Next != nil && p.Next.StopOffset <= interval.StartOffset; p = p.Next {
  174. }
  175. q := list.tail
  176. for ; q.Prev != nil && q.Prev.StartOffset >= interval.StopOffset; q = q.Prev {
  177. }
  178. // left side
  179. // interval after p.Next start
  180. if p.Next != nil && p.Next.StartOffset < interval.StartOffset {
  181. t := &Interval[T]{
  182. StartOffset: p.Next.StartOffset,
  183. StopOffset: interval.StartOffset,
  184. TsNs: p.Next.TsNs,
  185. Value: p.Next.Value,
  186. }
  187. p.Next = t
  188. if p != list.head {
  189. t.Prev = p
  190. }
  191. t.Next = interval
  192. interval.Prev = t
  193. } else {
  194. p.Next = interval
  195. if p != list.head {
  196. interval.Prev = p
  197. }
  198. }
  199. // right side
  200. // interval ends before p.Prev
  201. if q.Prev != nil && interval.StopOffset < q.Prev.StopOffset {
  202. t := &Interval[T]{
  203. StartOffset: interval.StopOffset,
  204. StopOffset: q.Prev.StopOffset,
  205. TsNs: q.Prev.TsNs,
  206. Value: q.Prev.Value,
  207. }
  208. q.Prev = t
  209. if q != list.tail {
  210. t.Next = q
  211. }
  212. interval.Next = t
  213. t.Prev = interval
  214. } else {
  215. q.Prev = interval
  216. if q != list.tail {
  217. interval.Next = q
  218. }
  219. }
  220. }
  221. func (list *IntervalList[T]) Len() int {
  222. list.Lock.RLock()
  223. defer list.Lock.RUnlock()
  224. var count int
  225. for t := list.head; t != nil; t = t.Next {
  226. count++
  227. }
  228. return count - 1
  229. }