github.com/yankunsam/loki/v2@v2.6.3-0.20220817130409-389df5235c27/pkg/querier/queryrange/ordering.go (about) 1 package queryrange 2 3 import ( 4 "sort" 5 6 "github.com/grafana/loki/pkg/logproto" 7 ) 8 9 /* 10 Utils for manipulating ordering 11 */ 12 13 type entries []logproto.Entry 14 15 func (m entries) start() int64 { 16 if len(m) == 0 { 17 return 0 18 } 19 return m[0].Timestamp.UnixNano() 20 } 21 22 type byDir struct { 23 markers []entries 24 direction logproto.Direction 25 labels string 26 } 27 28 func (a byDir) Len() int { return len(a.markers) } 29 func (a byDir) Swap(i, j int) { a.markers[i], a.markers[j] = a.markers[j], a.markers[i] } 30 func (a byDir) Less(i, j int) bool { 31 x, y := a.markers[i].start(), a.markers[j].start() 32 33 if a.direction == logproto.BACKWARD { 34 return x > y 35 } 36 return y > x 37 } 38 func (a byDir) EntriesCount() (n int) { 39 for _, m := range a.markers { 40 n += len(m) 41 } 42 return n 43 } 44 45 func (a byDir) merge() []logproto.Entry { 46 result := make([]logproto.Entry, 0, a.EntriesCount()) 47 48 sort.Sort(a) 49 for _, m := range a.markers { 50 result = append(result, m...) 51 } 52 return result 53 } 54 55 // priorityqueue is used for extracting a limited # of entries from a set of sorted streams 56 type priorityqueue struct { 57 streams []*logproto.Stream 58 direction logproto.Direction 59 } 60 61 func (pq *priorityqueue) Len() int { return len(pq.streams) } 62 63 func (pq *priorityqueue) Less(i, j int) bool { 64 if pq.direction == logproto.FORWARD { 65 return pq.streams[i].Entries[0].Timestamp.UnixNano() < pq.streams[j].Entries[0].Timestamp.UnixNano() 66 } 67 return pq.streams[i].Entries[0].Timestamp.UnixNano() > pq.streams[j].Entries[0].Timestamp.UnixNano() 68 69 } 70 71 func (pq *priorityqueue) Swap(i, j int) { 72 pq.streams[i], pq.streams[j] = pq.streams[j], pq.streams[i] 73 } 74 75 func (pq *priorityqueue) Push(x interface{}) { 76 stream := x.(*logproto.Stream) 77 pq.streams = append(pq.streams, stream) 78 } 79 80 // Pop returns a stream with one entry. It pops the first entry of the first stream 81 // then re-pushes the remainder of that stream if non-empty back into the queue 82 func (pq *priorityqueue) Pop() interface{} { 83 n := pq.Len() 84 stream := pq.streams[n-1] 85 pq.streams[n-1] = nil // avoid memory leak 86 pq.streams = pq.streams[:n-1] 87 88 // put the rest of the stream back into the priorityqueue if more entries exist 89 if len(stream.Entries) > 1 { 90 remaining := *stream 91 remaining.Entries = remaining.Entries[1:] 92 pq.Push(&remaining) 93 } 94 95 stream.Entries = stream.Entries[:1] 96 return stream 97 }