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.

188 lines
5.1 KiB

5 years ago
5 years ago
5 years ago
  1. package filesys
  2. import (
  3. "bytes"
  4. "io"
  5. "math"
  6. "github.com/chrislusf/seaweedfs/weed/glog"
  7. )
  8. type IntervalNode struct {
  9. Data []byte
  10. Offset int64
  11. Size int64
  12. Next *IntervalNode
  13. }
  14. type IntervalLinkedList struct {
  15. Head *IntervalNode
  16. Tail *IntervalNode
  17. }
  18. type ContinuousIntervals struct {
  19. lists []*IntervalLinkedList
  20. }
  21. func (list *IntervalLinkedList) Offset() int64 {
  22. return list.Head.Offset
  23. }
  24. func (list *IntervalLinkedList) Size() int64 {
  25. return list.Tail.Offset + list.Tail.Size - list.Head.Offset
  26. }
  27. func (list *IntervalLinkedList) addNodeToTail(node *IntervalNode) {
  28. // glog.V(0).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)
  29. list.Tail.Next = node
  30. list.Tail = node
  31. }
  32. func (list *IntervalLinkedList) addNodeToHead(node *IntervalNode) {
  33. // glog.V(0).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)
  34. node.Next = list.Head
  35. list.Head = node
  36. }
  37. func (list *IntervalLinkedList) ReadData(buf []byte, start, stop int64) {
  38. t := list.Head
  39. for {
  40. nodeStart, nodeStop := max(start, t.Offset), min(stop, t.Offset+t.Size)
  41. if nodeStart < nodeStop {
  42. // 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)
  43. copy(buf[nodeStart-start:], t.Data[nodeStart-t.Offset:nodeStop-t.Offset])
  44. }
  45. if t.Next == nil {
  46. break
  47. }
  48. t = t.Next
  49. }
  50. }
  51. func (c *ContinuousIntervals) TotalSize() (total int64) {
  52. for _, list := range c.lists {
  53. total += list.Size()
  54. }
  55. return
  56. }
  57. func (c *ContinuousIntervals) AddInterval(data []byte, offset int64) (hasOverlap bool) {
  58. interval := &IntervalNode{Data: data, Offset: offset, Size: int64(len(data))}
  59. var prevList, nextList *IntervalLinkedList
  60. for _, list := range c.lists {
  61. if list.Head.Offset == interval.Offset+interval.Size {
  62. nextList = list
  63. break
  64. }
  65. }
  66. for _, list := range c.lists {
  67. if list.Head.Offset+list.Size() == offset {
  68. list.addNodeToTail(interval)
  69. prevList = list
  70. break
  71. }
  72. if list.Head.Offset <= offset && offset < list.Head.Offset+list.Size() {
  73. if list.Tail.Offset <= offset {
  74. dataStartIndex := list.Tail.Offset + list.Tail.Size - offset
  75. glog.V(4).Infof("overlap data new [0,%d) same=%v", dataStartIndex, bytes.Compare(interval.Data[0:dataStartIndex], list.Tail.Data[len(list.Tail.Data)-int(dataStartIndex):]))
  76. interval.Data = interval.Data[dataStartIndex:]
  77. interval.Size -= dataStartIndex
  78. interval.Offset = offset + dataStartIndex
  79. glog.V(4).Infof("overlapping append as [%d,%d) dataSize=%d", interval.Offset, interval.Offset+interval.Size, len(interval.Data))
  80. list.addNodeToTail(interval)
  81. prevList = list
  82. break
  83. }
  84. glog.V(4).Infof("overlapped! interval is [%d,%d) dataSize=%d", interval.Offset, interval.Offset+interval.Size, len(interval.Data))
  85. hasOverlap = true
  86. return
  87. }
  88. }
  89. if prevList != nil && nextList != nil {
  90. // 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)
  91. prevList.Tail.Next = nextList.Head
  92. prevList.Tail = nextList.Tail
  93. c.removeList(nextList)
  94. } else if nextList != nil {
  95. // add to head was not done when checking
  96. nextList.addNodeToHead(interval)
  97. }
  98. if prevList == nil && nextList == nil {
  99. c.lists = append(c.lists, &IntervalLinkedList{
  100. Head: interval,
  101. Tail: interval,
  102. })
  103. }
  104. return
  105. }
  106. func (c *ContinuousIntervals) RemoveLargestIntervalLinkedList() *IntervalLinkedList {
  107. var maxSize int64
  108. maxIndex := -1
  109. for k, list := range c.lists {
  110. if maxSize <= list.Size() {
  111. maxSize = list.Size()
  112. maxIndex = k
  113. }
  114. }
  115. if maxSize <= 0 {
  116. return nil
  117. }
  118. t := c.lists[maxIndex]
  119. c.lists = append(c.lists[0:maxIndex], c.lists[maxIndex+1:]...)
  120. return t
  121. }
  122. func (c *ContinuousIntervals) removeList(target *IntervalLinkedList) {
  123. index := -1
  124. for k, list := range c.lists {
  125. if list.Offset() == target.Offset() {
  126. index = k
  127. }
  128. }
  129. if index < 0 {
  130. return
  131. }
  132. c.lists = append(c.lists[0:index], c.lists[index+1:]...)
  133. }
  134. func (c *ContinuousIntervals) ReadData(data []byte, startOffset int64) (offset int64, size int) {
  135. var minOffset int64 = math.MaxInt64
  136. var maxStop int64
  137. for _, list := range c.lists {
  138. start := max(startOffset, list.Offset())
  139. stop := min(startOffset+int64(len(data)), list.Offset()+list.Size())
  140. if start <= stop {
  141. list.ReadData(data[start-startOffset:], start, stop)
  142. minOffset = min(minOffset, start)
  143. maxStop = max(maxStop, stop)
  144. }
  145. }
  146. if minOffset == math.MaxInt64 {
  147. return 0, 0
  148. }
  149. offset = minOffset
  150. size = int(maxStop - offset)
  151. return
  152. }
  153. func (l *IntervalLinkedList) ToReader() io.Reader {
  154. var readers []io.Reader
  155. t := l.Head
  156. readers = append(readers, bytes.NewReader(t.Data))
  157. for t.Next != nil {
  158. t = t.Next
  159. readers = append(readers, bytes.NewReader(t.Data))
  160. }
  161. return io.MultiReader(readers...)
  162. }