github.com/cockroachdb/pebble@v1.1.2/merging_iter_heap.go (about) 1 // Copyright 2018 The LevelDB-Go and Pebble Authors. All rights reserved. Use 2 // of this source code is governed by a BSD-style license that can be found in 3 // the LICENSE file. 4 5 package pebble 6 7 type mergingIterHeap struct { 8 cmp Compare 9 reverse bool 10 items []*mergingIterLevel 11 } 12 13 func (h *mergingIterHeap) len() int { 14 return len(h.items) 15 } 16 17 func (h *mergingIterHeap) clear() { 18 h.items = h.items[:0] 19 } 20 21 func (h *mergingIterHeap) less(i, j int) bool { 22 ikey, jkey := h.items[i].iterKey, h.items[j].iterKey 23 if c := h.cmp(ikey.UserKey, jkey.UserKey); c != 0 { 24 if h.reverse { 25 return c > 0 26 } 27 return c < 0 28 } 29 if h.reverse { 30 return ikey.Trailer < jkey.Trailer 31 } 32 return ikey.Trailer > jkey.Trailer 33 } 34 35 func (h *mergingIterHeap) swap(i, j int) { 36 h.items[i], h.items[j] = h.items[j], h.items[i] 37 } 38 39 // init, fix, up and down are copied from the go stdlib. 40 func (h *mergingIterHeap) init() { 41 // heapify 42 n := h.len() 43 for i := n/2 - 1; i >= 0; i-- { 44 h.down(i, n) 45 } 46 } 47 48 func (h *mergingIterHeap) fix(i int) { 49 if !h.down(i, h.len()) { 50 h.up(i) 51 } 52 } 53 54 func (h *mergingIterHeap) pop() *mergingIterLevel { 55 n := h.len() - 1 56 h.swap(0, n) 57 h.down(0, n) 58 item := h.items[n] 59 h.items = h.items[:n] 60 return item 61 } 62 63 func (h *mergingIterHeap) up(j int) { 64 for { 65 i := (j - 1) / 2 // parent 66 if i == j || !h.less(j, i) { 67 break 68 } 69 h.swap(i, j) 70 j = i 71 } 72 } 73 74 func (h *mergingIterHeap) down(i0, n int) bool { 75 i := i0 76 for { 77 j1 := 2*i + 1 78 if j1 >= n || j1 < 0 { // j1 < 0 after int overflow 79 break 80 } 81 j := j1 // left child 82 if j2 := j1 + 1; j2 < n && h.less(j2, j1) { 83 j = j2 // = 2*i + 2 // right child 84 } 85 if !h.less(j, i) { 86 break 87 } 88 h.swap(i, j) 89 i = j 90 } 91 return i > i0 92 }