github.com/zuoyebang/bitalosdb@v1.1.1-0.20240516111551-79a8c4d8ce20/internal/cache/lfucache/merging_iter_heap.go (about)

     1  // Copyright 2021 The Bitalosdb author(hustxrb@163.com) and other contributors.
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at
     6  //
     7  //     http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12  // See the License for the specific language governing permissions and
    13  // limitations under the License.
    14  
    15  package lfucache
    16  
    17  import "bytes"
    18  
    19  type mergingIterItem struct {
    20  	index int
    21  	key   internalKey
    22  	value []byte
    23  }
    24  
    25  type mergingIterHeap struct {
    26  	reverse bool
    27  	items   []mergingIterItem
    28  }
    29  
    30  func (h *mergingIterHeap) len() int {
    31  	return len(h.items)
    32  }
    33  
    34  func (h *mergingIterHeap) clear() {
    35  	h.items = h.items[:0]
    36  }
    37  
    38  func (h *mergingIterHeap) less(i, j int) bool {
    39  	ikey, jkey := h.items[i].key, h.items[j].key
    40  	if c := bytes.Compare(ikey.UserKey, jkey.UserKey); c != 0 {
    41  		if h.reverse {
    42  			return c > 0
    43  		}
    44  		return c < 0
    45  	}
    46  	if h.reverse {
    47  		return ikey.Trailer < jkey.Trailer
    48  	}
    49  	return ikey.Trailer > jkey.Trailer
    50  }
    51  
    52  func (h *mergingIterHeap) swap(i, j int) {
    53  	h.items[i], h.items[j] = h.items[j], h.items[i]
    54  }
    55  
    56  func (h *mergingIterHeap) init() {
    57  	n := h.len()
    58  	for i := n/2 - 1; i >= 0; i-- {
    59  		h.down(i, n)
    60  	}
    61  }
    62  
    63  func (h *mergingIterHeap) fix(i int) {
    64  	if !h.down(i, h.len()) {
    65  		h.up(i)
    66  	}
    67  }
    68  
    69  func (h *mergingIterHeap) pop() *mergingIterItem {
    70  	n := h.len() - 1
    71  	h.swap(0, n)
    72  	h.down(0, n)
    73  	item := &h.items[n]
    74  	h.items = h.items[:n]
    75  	return item
    76  }
    77  
    78  func (h *mergingIterHeap) up(j int) {
    79  	for {
    80  		i := (j - 1) / 2
    81  		if i == j || !h.less(j, i) {
    82  			break
    83  		}
    84  		h.swap(i, j)
    85  		j = i
    86  	}
    87  }
    88  
    89  func (h *mergingIterHeap) down(i0, n int) bool {
    90  	i := i0
    91  	for {
    92  		j1 := 2*i + 1
    93  		if j1 >= n || j1 < 0 {
    94  			break
    95  		}
    96  		j := j1
    97  		if j2 := j1 + 1; j2 < n && h.less(j2, j1) {
    98  			j = j2
    99  		}
   100  		if !h.less(j, i) {
   101  			break
   102  		}
   103  		h.swap(i, j)
   104  		i = j
   105  	}
   106  	return i > i0
   107  }