dirty_page_interval.go 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220
  1. package filesys
  2. import (
  3. "bytes"
  4. "io"
  5. "math"
  6. )
  7. type IntervalNode struct {
  8. Data []byte
  9. Offset int64
  10. Size int64
  11. Next *IntervalNode
  12. }
  13. type IntervalLinkedList struct {
  14. Head *IntervalNode
  15. Tail *IntervalNode
  16. }
  17. type ContinuousIntervals struct {
  18. lists []*IntervalLinkedList
  19. }
  20. func (list *IntervalLinkedList) Offset() int64 {
  21. return list.Head.Offset
  22. }
  23. func (list *IntervalLinkedList) Size() int64 {
  24. return list.Tail.Offset + list.Tail.Size - list.Head.Offset
  25. }
  26. func (list *IntervalLinkedList) addNodeToTail(node *IntervalNode) {
  27. // glog.V(4).Infof("add to tail [%d,%d) + [%d,%d) => [%d,%d)", list.Head.Offset, list.Tail.Offset+list.Tail.Size, node.Offset, node.Offset+node.Size, list.Head.Offset, node.Offset+node.Size)
  28. list.Tail.Next = node
  29. list.Tail = node
  30. }
  31. func (list *IntervalLinkedList) addNodeToHead(node *IntervalNode) {
  32. // glog.V(4).Infof("add to head [%d,%d) + [%d,%d) => [%d,%d)", node.Offset, node.Offset+node.Size, list.Head.Offset, list.Tail.Offset+list.Tail.Size, node.Offset, list.Tail.Offset+list.Tail.Size)
  33. node.Next = list.Head
  34. list.Head = node
  35. }
  36. func (list *IntervalLinkedList) ReadData(buf []byte, start, stop int64) {
  37. t := list.Head
  38. for {
  39. nodeStart, nodeStop := max(start, t.Offset), min(stop, t.Offset+t.Size)
  40. if nodeStart < nodeStop {
  41. // glog.V(0).Infof("copying start=%d stop=%d t=[%d,%d) t.data=%d => bufSize=%d nodeStart=%d, nodeStop=%d", start, stop, t.Offset, t.Offset+t.Size, len(t.Data), len(buf), nodeStart, nodeStop)
  42. copy(buf[nodeStart-start:], t.Data[nodeStart-t.Offset:nodeStop-t.Offset])
  43. }
  44. if t.Next == nil {
  45. break
  46. }
  47. t = t.Next
  48. }
  49. }
  50. func (c *ContinuousIntervals) TotalSize() (total int64) {
  51. for _, list := range c.lists {
  52. total += list.Size()
  53. }
  54. return
  55. }
  56. func subList(list *IntervalLinkedList, start, stop int64) *IntervalLinkedList {
  57. var nodes []*IntervalNode
  58. for t := list.Head; t != nil; t = t.Next {
  59. nodeStart, nodeStop := max(start, t.Offset), min(stop, t.Offset+t.Size)
  60. if nodeStart >= nodeStop {
  61. // skip non overlapping IntervalNode
  62. continue
  63. }
  64. nodes = append(nodes, &IntervalNode{
  65. Data: t.Data[nodeStart-t.Offset : nodeStop-t.Offset],
  66. Offset: nodeStart,
  67. Size: nodeStop - nodeStart,
  68. Next: nil,
  69. })
  70. }
  71. for i := 1; i < len(nodes); i++ {
  72. nodes[i-1].Next = nodes[i]
  73. }
  74. return &IntervalLinkedList{
  75. Head: nodes[0],
  76. Tail: nodes[len(nodes)-1],
  77. }
  78. }
  79. func (c *ContinuousIntervals) AddInterval(data []byte, offset int64) {
  80. interval := &IntervalNode{Data: data, Offset: offset, Size: int64(len(data))}
  81. var newLists []*IntervalLinkedList
  82. for _, list := range c.lists {
  83. // if list is to the left of new interval, add to the new list
  84. if list.Tail.Offset+list.Tail.Size <= interval.Offset {
  85. newLists = append(newLists, list)
  86. }
  87. // if list is to the right of new interval, add to the new list
  88. if interval.Offset+interval.Size <= list.Head.Offset {
  89. newLists = append(newLists, list)
  90. }
  91. // if new interval overwrite the right part of the list
  92. if list.Head.Offset < interval.Offset && interval.Offset < list.Tail.Offset+list.Tail.Size {
  93. // create a new list of the left part of existing list
  94. newLists = append(newLists, subList(list, list.Offset(), interval.Offset))
  95. }
  96. // if new interval overwrite the left part of the list
  97. if list.Head.Offset < interval.Offset+interval.Size && interval.Offset+interval.Size < list.Tail.Offset+list.Tail.Size {
  98. // create a new list of the right part of existing list
  99. newLists = append(newLists, subList(list, interval.Offset+interval.Size, list.Tail.Offset+list.Tail.Size))
  100. }
  101. // skip anything that is fully overwritten by the new interval
  102. }
  103. c.lists = newLists
  104. // add the new interval to the lists, connecting neighbor lists
  105. var prevList, nextList *IntervalLinkedList
  106. for _, list := range c.lists {
  107. if list.Head.Offset == interval.Offset+interval.Size {
  108. nextList = list
  109. break
  110. }
  111. }
  112. for _, list := range c.lists {
  113. if list.Head.Offset+list.Size() == offset {
  114. list.addNodeToTail(interval)
  115. prevList = list
  116. break
  117. }
  118. }
  119. if prevList != nil && nextList != nil {
  120. // glog.V(4).Infof("connecting [%d,%d) + [%d,%d) => [%d,%d)", prevList.Head.Offset, prevList.Tail.Offset+prevList.Tail.Size, nextList.Head.Offset, nextList.Tail.Offset+nextList.Tail.Size, prevList.Head.Offset, nextList.Tail.Offset+nextList.Tail.Size)
  121. prevList.Tail.Next = nextList.Head
  122. prevList.Tail = nextList.Tail
  123. c.removeList(nextList)
  124. } else if nextList != nil {
  125. // add to head was not done when checking
  126. nextList.addNodeToHead(interval)
  127. }
  128. if prevList == nil && nextList == nil {
  129. c.lists = append(c.lists, &IntervalLinkedList{
  130. Head: interval,
  131. Tail: interval,
  132. })
  133. }
  134. return
  135. }
  136. func (c *ContinuousIntervals) RemoveLargestIntervalLinkedList() *IntervalLinkedList {
  137. var maxSize int64
  138. maxIndex := -1
  139. for k, list := range c.lists {
  140. if maxSize <= list.Size() {
  141. maxSize = list.Size()
  142. maxIndex = k
  143. }
  144. }
  145. if maxSize <= 0 {
  146. return nil
  147. }
  148. t := c.lists[maxIndex]
  149. c.lists = append(c.lists[0:maxIndex], c.lists[maxIndex+1:]...)
  150. return t
  151. }
  152. func (c *ContinuousIntervals) removeList(target *IntervalLinkedList) {
  153. index := -1
  154. for k, list := range c.lists {
  155. if list.Offset() == target.Offset() {
  156. index = k
  157. }
  158. }
  159. if index < 0 {
  160. return
  161. }
  162. c.lists = append(c.lists[0:index], c.lists[index+1:]...)
  163. }
  164. func (c *ContinuousIntervals) ReadData(data []byte, startOffset int64) (offset int64, size int) {
  165. var minOffset int64 = math.MaxInt64
  166. var maxStop int64
  167. for _, list := range c.lists {
  168. start := max(startOffset, list.Offset())
  169. stop := min(startOffset+int64(len(data)), list.Offset()+list.Size())
  170. if start <= stop {
  171. list.ReadData(data[start-startOffset:], start, stop)
  172. minOffset = min(minOffset, start)
  173. maxStop = max(maxStop, stop)
  174. }
  175. }
  176. if minOffset == math.MaxInt64 {
  177. return 0, 0
  178. }
  179. offset = minOffset
  180. size = int(maxStop - offset)
  181. return
  182. }
  183. func (l *IntervalLinkedList) ToReader() io.Reader {
  184. var readers []io.Reader
  185. t := l.Head
  186. readers = append(readers, bytes.NewReader(t.Data))
  187. for t.Next != nil {
  188. t = t.Next
  189. readers = append(readers, bytes.NewReader(t.Data))
  190. }
  191. return io.MultiReader(readers...)
  192. }