Line data Source code
1 : package pebble
2 :
3 : import "github.com/cockroachdb/pebble/internal/base"
4 :
5 : // The maximum number of elements in the readCompactions queue.
6 : // We want to limit the number of elements so that we only do
7 : // compactions for ranges which are being read recently.
8 : const readCompactionMaxQueueSize = 5
9 :
10 : // The readCompactionQueue is a queue of read compactions with
11 : // 0 overlapping ranges.
12 : type readCompactionQueue struct {
13 : // Invariant: A contiguous prefix of the queue contains
14 : // all the elements in the queue, in order of insertion.
15 : // When we remove duplicates from the queue, we break
16 : // the invariant that a contiguous prefix of the queue
17 : // has all the elements in it. To fix this, we shift
18 : // the elements of the queue to the left. This is cheap
19 : // because the queue has a max length of 5.
20 : queue [readCompactionMaxQueueSize]*readCompaction
21 :
22 : // The size of the queue which is occupied.
23 : // A size of k, implies that the first k elements
24 : // of the queue are occupied.
25 : // The size will be <= readCompactionMaxQueueSize.
26 : size int
27 : }
28 :
29 : // combine should be used to combine an older queue with a newer
30 : // queue.
31 0 : func (qu *readCompactionQueue) combine(newQu *readCompactionQueue, cmp base.Compare) {
32 0 :
33 0 : for i := 0; i < newQu.size; i++ {
34 0 : qu.add(newQu.queue[i], cmp)
35 0 : }
36 : }
37 :
38 : // add adds read compactions to the queue, while maintaining the invariant
39 : // that there are no overlapping ranges in the queue.
40 0 : func (qu *readCompactionQueue) add(rc *readCompaction, cmp base.Compare) {
41 0 : sz := qu.size
42 0 : for i := 0; i < sz; i++ {
43 0 : left := qu.queue[i]
44 0 : right := rc
45 0 : if cmp(left.start, right.start) > 0 {
46 0 : left, right = right, left
47 0 : }
48 0 : if cmp(right.start, left.end) <= 0 {
49 0 : qu.queue[i] = nil
50 0 : qu.size--
51 0 : }
52 : }
53 :
54 : // Get rid of the holes which may have been formed
55 : // in the queue.
56 0 : qu.shiftLeft()
57 0 :
58 0 : if qu.size == readCompactionMaxQueueSize {
59 0 : // Make space at the end.
60 0 : copy(qu.queue[0:], qu.queue[1:])
61 0 : qu.queue[qu.size-1] = rc
62 0 : } else {
63 0 : qu.size++
64 0 : qu.queue[qu.size-1] = rc
65 0 : }
66 : }
67 :
68 : // Shifts the non-nil elements of the queue to the left so
69 : // that a continguous prefix of the queue is non-nil.
70 0 : func (qu *readCompactionQueue) shiftLeft() {
71 0 : nilPos := -1
72 0 : for i := 0; i < readCompactionMaxQueueSize; i++ {
73 0 : if qu.queue[i] == nil && nilPos == -1 {
74 0 : nilPos = i
75 0 : } else if qu.queue[i] != nil && nilPos != -1 {
76 0 : qu.queue[nilPos] = qu.queue[i]
77 0 : qu.queue[i] = nil
78 0 : nilPos++
79 0 : }
80 : }
81 : }
82 :
83 : // remove will remove the oldest element from the queue.
84 0 : func (qu *readCompactionQueue) remove() *readCompaction {
85 0 : if qu.size == 0 {
86 0 : return nil
87 0 : }
88 :
89 0 : c := qu.queue[0]
90 0 : copy(qu.queue[0:], qu.queue[1:])
91 0 : qu.queue[qu.size-1] = nil
92 0 : qu.size--
93 0 : return c
94 : }
|