package table
import (
"bytes"
"github.com/dgraph-io/badger/v4/y"
)
type MergeIterator struct {
left node
right node
small *node
curKey []byte
reverse bool
}
type node struct {
valid bool
key []byte
iter y .Iterator
merge *MergeIterator
concat *ConcatIterator
}
func (n *node ) setIterator (iter y .Iterator ) {
n .iter = iter
n .merge , _ = iter .(*MergeIterator )
n .concat , _ = iter .(*ConcatIterator )
}
func (n *node ) setKey () {
switch {
case n .merge != nil :
n .valid = n .merge .small .valid
if n .valid {
n .key = n .merge .small .key
}
case n .concat != nil :
n .valid = n .concat .Valid ()
if n .valid {
n .key = n .concat .Key ()
}
default :
n .valid = n .iter .Valid ()
if n .valid {
n .key = n .iter .Key ()
}
}
}
func (n *node ) next () {
switch {
case n .merge != nil :
n .merge .Next ()
case n .concat != nil :
n .concat .Next ()
default :
n .iter .Next ()
}
n .setKey ()
}
func (n *node ) rewind () {
n .iter .Rewind ()
n .setKey ()
}
func (n *node ) seek (key []byte ) {
n .iter .Seek (key )
n .setKey ()
}
func (mi *MergeIterator ) fix () {
if !mi .bigger ().valid {
return
}
if !mi .small .valid {
mi .swapSmall ()
return
}
cmp := y .CompareKeys (mi .small .key , mi .bigger ().key )
switch {
case cmp == 0 :
mi .right .next ()
if &mi .right == mi .small {
mi .swapSmall ()
}
return
case cmp < 0 :
if mi .reverse {
mi .swapSmall ()
} else {
}
return
default :
if mi .reverse {
} else {
mi .swapSmall ()
}
return
}
}
func (mi *MergeIterator ) bigger () *node {
if mi .small == &mi .left {
return &mi .right
}
return &mi .left
}
func (mi *MergeIterator ) swapSmall () {
if mi .small == &mi .left {
mi .small = &mi .right
return
}
if mi .small == &mi .right {
mi .small = &mi .left
return
}
}
func (mi *MergeIterator ) Next () {
for mi .Valid () {
if !bytes .Equal (mi .small .key , mi .curKey ) {
break
}
mi .small .next ()
mi .fix ()
}
mi .setCurrent ()
}
func (mi *MergeIterator ) setCurrent () {
mi .curKey = append (mi .curKey [:0 ], mi .small .key ...)
}
func (mi *MergeIterator ) Rewind () {
mi .left .rewind ()
mi .right .rewind ()
mi .fix ()
mi .setCurrent ()
}
func (mi *MergeIterator ) Seek (key []byte ) {
mi .left .seek (key )
mi .right .seek (key )
mi .fix ()
mi .setCurrent ()
}
func (mi *MergeIterator ) Valid () bool {
return mi .small .valid
}
func (mi *MergeIterator ) Key () []byte {
return mi .small .key
}
func (mi *MergeIterator ) Value () y .ValueStruct {
return mi .small .iter .Value ()
}
func (mi *MergeIterator ) Close () error {
err1 := mi .left .iter .Close ()
err2 := mi .right .iter .Close ()
if err1 != nil {
return y .Wrap (err1 , "MergeIterator" )
}
return y .Wrap (err2 , "MergeIterator" )
}
func NewMergeIterator (iters []y .Iterator , reverse bool ) y .Iterator {
switch len (iters ) {
case 0 :
return nil
case 1 :
return iters [0 ]
case 2 :
mi := &MergeIterator {
reverse : reverse ,
}
mi .left .setIterator (iters [0 ])
mi .right .setIterator (iters [1 ])
mi .small = &mi .left
return mi
}
mid := len (iters ) / 2
return NewMergeIterator (
[]y .Iterator {
NewMergeIterator (iters [:mid ], reverse ),
NewMergeIterator (iters [mid :], reverse ),
}, reverse )
}
The pages are generated with Golds v0.8.4 . (GOOS=linux GOARCH=amd64)
Golds is a Go 101 project developed by Tapir Liu .
PR and bug reports are welcome and can be submitted to the issue list .
Please follow @zigo_101 (reachable from the left QR code) to get the latest news of Golds .