github.com/petermattis/pebble@v0.0.0-20190905164901-ab51a2166067/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 mergingIterItem struct { 8 index int 9 key InternalKey 10 value []byte 11 } 12 13 type mergingIterHeap struct { 14 cmp Compare 15 reverse bool 16 items []mergingIterItem 17 } 18 19 func (h *mergingIterHeap) len() int { 20 return len(h.items) 21 } 22 23 func (h *mergingIterHeap) less(i, j int) bool { 24 ikey, jkey := h.items[i].key, h.items[j].key 25 if c := h.cmp(ikey.UserKey, jkey.UserKey); c != 0 { 26 if h.reverse { 27 return c > 0 28 } 29 return c < 0 30 } 31 if h.reverse { 32 return ikey.Trailer < jkey.Trailer 33 } 34 return ikey.Trailer > jkey.Trailer 35 } 36 37 func (h *mergingIterHeap) swap(i, j int) { 38 h.items[i], h.items[j] = h.items[j], h.items[i] 39 } 40 41 // init, fix, up and down are copied from the go stdlib. 42 func (h *mergingIterHeap) init() { 43 // heapify 44 n := h.len() 45 for i := n/2 - 1; i >= 0; i-- { 46 h.down(i, n) 47 } 48 } 49 50 func (h *mergingIterHeap) fix(i int) { 51 if !h.down(i, h.len()) { 52 h.up(i) 53 } 54 } 55 56 func (h *mergingIterHeap) pop() *mergingIterItem { 57 n := h.len() - 1 58 h.swap(0, n) 59 h.down(0, n) 60 item := &h.items[n] 61 h.items = h.items[:n] 62 return item 63 } 64 65 func (h *mergingIterHeap) up(j int) { 66 for { 67 i := (j - 1) / 2 // parent 68 if i == j || !h.less(j, i) { 69 break 70 } 71 h.swap(i, j) 72 j = i 73 } 74 } 75 76 func (h *mergingIterHeap) down(i0, n int) bool { 77 i := i0 78 for { 79 j1 := 2*i + 1 80 if j1 >= n || j1 < 0 { // j1 < 0 after int overflow 81 break 82 } 83 j := j1 // left child 84 if j2 := j1 + 1; j2 < n && h.less(j2, j1) { 85 j = j2 // = 2*i + 2 // right child 86 } 87 if !h.less(j, i) { 88 break 89 } 90 h.swap(i, j) 91 i = j 92 } 93 return i > i0 94 }