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.

258 lines
7.0 KiB

5 years ago
5 years ago
5 years ago
5 years ago
4 years ago
  1. package filesys
  2. import (
  3. "bytes"
  4. "io"
  5. "github.com/chrislusf/seaweedfs/weed/util"
  6. "github.com/valyala/bytebufferpool"
  7. )
  8. type IntervalNode struct {
  9. Data []byte
  10. Offset int64
  11. Size int64
  12. Next *IntervalNode
  13. Buffer *bytebufferpool.ByteBuffer
  14. }
  15. func (l *IntervalNode) Bytes() []byte {
  16. data := l.Data
  17. if data == nil {
  18. data = l.Buffer.Bytes()
  19. }
  20. return data
  21. }
  22. type IntervalLinkedList struct {
  23. Head *IntervalNode
  24. Tail *IntervalNode
  25. }
  26. type ContinuousIntervals struct {
  27. lists []*IntervalLinkedList
  28. }
  29. func NewIntervalLinkedList(head, tail *IntervalNode) *IntervalLinkedList {
  30. list := &IntervalLinkedList{
  31. Head: head,
  32. Tail: tail,
  33. }
  34. return list
  35. }
  36. func (list *IntervalLinkedList) Destroy() {
  37. for t := list.Head; t != nil; t = t.Next {
  38. if t.Buffer != nil {
  39. bytebufferpool.Put(t.Buffer)
  40. }
  41. }
  42. }
  43. func (list *IntervalLinkedList) Offset() int64 {
  44. return list.Head.Offset
  45. }
  46. func (list *IntervalLinkedList) Size() int64 {
  47. return list.Tail.Offset + list.Tail.Size - list.Head.Offset
  48. }
  49. func (list *IntervalLinkedList) addNodeToTail(node *IntervalNode) {
  50. // 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)
  51. if list.Tail.Buffer == nil {
  52. list.Tail.Buffer = bytebufferpool.Get()
  53. list.Tail.Buffer.Write(list.Tail.Data)
  54. list.Tail.Data = nil
  55. }
  56. list.Tail.Buffer.Write(node.Data)
  57. list.Tail.Size += int64(len(node.Data))
  58. return
  59. }
  60. func (list *IntervalLinkedList) addNodeToHead(node *IntervalNode) {
  61. // 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)
  62. node.Next = list.Head
  63. list.Head = node
  64. }
  65. func (list *IntervalLinkedList) ReadData(buf []byte, start, stop int64) {
  66. t := list.Head
  67. for {
  68. nodeStart, nodeStop := max(start, t.Offset), min(stop, t.Offset+t.Size)
  69. if nodeStart < nodeStop {
  70. // 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)
  71. copy(buf[nodeStart-start:], t.Bytes()[nodeStart-t.Offset:nodeStop-t.Offset])
  72. }
  73. if t.Next == nil {
  74. break
  75. }
  76. t = t.Next
  77. }
  78. }
  79. func (c *ContinuousIntervals) TotalSize() (total int64) {
  80. for _, list := range c.lists {
  81. total += list.Size()
  82. }
  83. return
  84. }
  85. func subList(list *IntervalLinkedList, start, stop int64) *IntervalLinkedList {
  86. var nodes []*IntervalNode
  87. for t := list.Head; t != nil; t = t.Next {
  88. nodeStart, nodeStop := max(start, t.Offset), min(stop, t.Offset+t.Size)
  89. if nodeStart >= nodeStop {
  90. // skip non overlapping IntervalNode
  91. continue
  92. }
  93. data := t.Bytes()[nodeStart-t.Offset : nodeStop-t.Offset]
  94. if t.Data == nil {
  95. // need to clone if the bytes is from byte buffer
  96. t := make([]byte, len(data))
  97. copy(t, data)
  98. data = t
  99. }
  100. nodes = append(nodes, &IntervalNode{
  101. Data: data,
  102. Offset: nodeStart,
  103. Size: nodeStop - nodeStart,
  104. Next: nil,
  105. })
  106. }
  107. for i := 1; i < len(nodes); i++ {
  108. nodes[i-1].Next = nodes[i]
  109. }
  110. return NewIntervalLinkedList(nodes[0], nodes[len(nodes)-1])
  111. }
  112. func (c *ContinuousIntervals) AddInterval(data []byte, offset int64) {
  113. interval := &IntervalNode{Data: data, Offset: offset, Size: int64(len(data))}
  114. // append to the tail and return
  115. if len(c.lists) == 1 {
  116. lastSpan := c.lists[0]
  117. if lastSpan.Tail.Offset + lastSpan.Tail.Size == offset {
  118. lastSpan.addNodeToTail(interval)
  119. return
  120. }
  121. }
  122. var newLists []*IntervalLinkedList
  123. for _, list := range c.lists {
  124. // if list is to the left of new interval, add to the new list
  125. if list.Tail.Offset+list.Tail.Size <= interval.Offset {
  126. newLists = append(newLists, list)
  127. }
  128. // if list is to the right of new interval, add to the new list
  129. if interval.Offset+interval.Size <= list.Head.Offset {
  130. newLists = append(newLists, list)
  131. }
  132. // if new interval overwrite the right part of the list
  133. if list.Head.Offset < interval.Offset && interval.Offset < list.Tail.Offset+list.Tail.Size {
  134. // create a new list of the left part of existing list
  135. newLists = append(newLists, subList(list, list.Offset(), interval.Offset))
  136. }
  137. // if new interval overwrite the left part of the list
  138. if list.Head.Offset < interval.Offset+interval.Size && interval.Offset+interval.Size < list.Tail.Offset+list.Tail.Size {
  139. // create a new list of the right part of existing list
  140. newLists = append(newLists, subList(list, interval.Offset+interval.Size, list.Tail.Offset+list.Tail.Size))
  141. }
  142. // skip anything that is fully overwritten by the new interval
  143. }
  144. c.lists = newLists
  145. // add the new interval to the lists, connecting neighbor lists
  146. var prevList, nextList *IntervalLinkedList
  147. for _, list := range c.lists {
  148. if list.Head.Offset == interval.Offset+interval.Size {
  149. nextList = list
  150. break
  151. }
  152. }
  153. for _, list := range c.lists {
  154. if list.Head.Offset+list.Size() == offset {
  155. list.addNodeToTail(interval)
  156. prevList = list
  157. break
  158. }
  159. }
  160. if prevList != nil && nextList != nil {
  161. // 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)
  162. prevList.Tail.Next = nextList.Head
  163. prevList.Tail = nextList.Tail
  164. c.removeList(nextList)
  165. } else if nextList != nil {
  166. // add to head was not done when checking
  167. nextList.addNodeToHead(interval)
  168. }
  169. if prevList == nil && nextList == nil {
  170. c.lists = append(c.lists, NewIntervalLinkedList(interval, interval))
  171. }
  172. return
  173. }
  174. func (c *ContinuousIntervals) RemoveLargestIntervalLinkedList() *IntervalLinkedList {
  175. var maxSize int64
  176. maxIndex, maxOffset := -1, int64(-1)
  177. for k, list := range c.lists {
  178. listSize := list.Size()
  179. if maxSize < listSize || (maxSize == listSize && list.Offset() < maxOffset ) {
  180. maxSize = listSize
  181. maxIndex, maxOffset = k, list.Offset()
  182. }
  183. }
  184. if maxSize <= 0 {
  185. return nil
  186. }
  187. t := c.lists[maxIndex]
  188. c.lists = append(c.lists[0:maxIndex], c.lists[maxIndex+1:]...)
  189. return t
  190. }
  191. func (c *ContinuousIntervals) removeList(target *IntervalLinkedList) {
  192. index := -1
  193. for k, list := range c.lists {
  194. if list.Offset() == target.Offset() {
  195. index = k
  196. }
  197. }
  198. if index < 0 {
  199. return
  200. }
  201. c.lists = append(c.lists[0:index], c.lists[index+1:]...)
  202. }
  203. func (c *ContinuousIntervals) ReadDataAt(data []byte, startOffset int64) (maxStop int64) {
  204. for _, list := range c.lists {
  205. start := max(startOffset, list.Offset())
  206. stop := min(startOffset+int64(len(data)), list.Offset()+list.Size())
  207. if start < stop {
  208. list.ReadData(data[start-startOffset:], start, stop)
  209. maxStop = max(maxStop, stop)
  210. }
  211. }
  212. return
  213. }
  214. func (l *IntervalLinkedList) ToReader() io.Reader {
  215. var readers []io.Reader
  216. t := l.Head
  217. readers = append(readers, util.NewBytesReader(t.Bytes()))
  218. for t.Next != nil {
  219. t = t.Next
  220. readers = append(readers, bytes.NewReader(t.Bytes()))
  221. }
  222. if len(readers) == 1 {
  223. return readers[0]
  224. }
  225. return io.MultiReader(readers...)
  226. }