github.com/df-mc/goleveldb@v1.1.9/leveldb/db_iter.go (about)

     1  // Copyright (c) 2012, Suryandaru Triandana <syndtr@gmail.com>
     2  // All rights reserved.
     3  //
     4  // Use of this source code is governed by a BSD-style license that can be
     5  // found in the LICENSE file.
     6  
     7  package leveldb
     8  
     9  import (
    10  	"errors"
    11  	"math/rand"
    12  	"runtime"
    13  	"sync"
    14  	"sync/atomic"
    15  
    16  	"github.com/df-mc/goleveldb/leveldb/iterator"
    17  	"github.com/df-mc/goleveldb/leveldb/opt"
    18  	"github.com/df-mc/goleveldb/leveldb/util"
    19  )
    20  
    21  var (
    22  	errInvalidInternalKey = errors.New("leveldb: Iterator: invalid internal key")
    23  )
    24  
    25  type memdbReleaser struct {
    26  	once sync.Once
    27  	m    *memDB
    28  }
    29  
    30  func (mr *memdbReleaser) Release() {
    31  	mr.once.Do(func() {
    32  		mr.m.decref()
    33  	})
    34  }
    35  
    36  func (db *DB) newRawIterator(auxm *memDB, auxt tFiles, slice *util.Range, ro *opt.ReadOptions) iterator.Iterator {
    37  	strict := opt.GetStrict(db.s.o.Options, ro, opt.StrictReader)
    38  	em, fm := db.getMems()
    39  	v := db.s.version()
    40  
    41  	tableIts := v.getIterators(slice, ro)
    42  	n := len(tableIts) + len(auxt) + 3
    43  	its := make([]iterator.Iterator, 0, n)
    44  
    45  	if auxm != nil {
    46  		ami := auxm.NewIterator(slice)
    47  		ami.SetReleaser(&memdbReleaser{m: auxm})
    48  		its = append(its, ami)
    49  	}
    50  	for _, t := range auxt {
    51  		its = append(its, v.s.tops.newIterator(t, slice, ro))
    52  	}
    53  
    54  	emi := em.NewIterator(slice)
    55  	emi.SetReleaser(&memdbReleaser{m: em})
    56  	its = append(its, emi)
    57  	if fm != nil {
    58  		fmi := fm.NewIterator(slice)
    59  		fmi.SetReleaser(&memdbReleaser{m: fm})
    60  		its = append(its, fmi)
    61  	}
    62  	its = append(its, tableIts...)
    63  	mi := iterator.NewMergedIterator(its, db.s.icmp, strict)
    64  	mi.SetReleaser(&versionReleaser{v: v})
    65  	return mi
    66  }
    67  
    68  func (db *DB) newIterator(auxm *memDB, auxt tFiles, seq uint64, slice *util.Range, ro *opt.ReadOptions) *dbIter {
    69  	var islice *util.Range
    70  	if slice != nil {
    71  		islice = &util.Range{}
    72  		if slice.Start != nil {
    73  			islice.Start = makeInternalKey(nil, slice.Start, keyMaxSeq, keyTypeSeek)
    74  		}
    75  		if slice.Limit != nil {
    76  			islice.Limit = makeInternalKey(nil, slice.Limit, keyMaxSeq, keyTypeSeek)
    77  		}
    78  	}
    79  	rawIter := db.newRawIterator(auxm, auxt, islice, ro)
    80  	iter := &dbIter{
    81  		db:              db,
    82  		icmp:            db.s.icmp,
    83  		iter:            rawIter,
    84  		seq:             seq,
    85  		strict:          opt.GetStrict(db.s.o.Options, ro, opt.StrictReader),
    86  		disableSampling: db.s.o.GetDisableSeeksCompaction() || db.s.o.GetIteratorSamplingRate() <= 0,
    87  		key:             make([]byte, 0),
    88  		value:           make([]byte, 0),
    89  	}
    90  	if !iter.disableSampling {
    91  		iter.samplingGap = db.iterSamplingRate()
    92  	}
    93  	atomic.AddInt32(&db.aliveIters, 1)
    94  	runtime.SetFinalizer(iter, (*dbIter).Release)
    95  	return iter
    96  }
    97  
    98  func (db *DB) iterSamplingRate() int {
    99  	return rand.Intn(2 * db.s.o.GetIteratorSamplingRate())
   100  }
   101  
   102  type dir int
   103  
   104  const (
   105  	dirReleased dir = iota - 1
   106  	dirSOI
   107  	dirEOI
   108  	dirBackward
   109  	dirForward
   110  )
   111  
   112  // dbIter represent an interator states over a database session.
   113  type dbIter struct {
   114  	db              *DB
   115  	icmp            *iComparer
   116  	iter            iterator.Iterator
   117  	seq             uint64
   118  	strict          bool
   119  	disableSampling bool
   120  
   121  	samplingGap int
   122  	dir         dir
   123  	key         []byte
   124  	value       []byte
   125  	err         error
   126  	releaser    util.Releaser
   127  }
   128  
   129  func (i *dbIter) sampleSeek() {
   130  	if i.disableSampling {
   131  		return
   132  	}
   133  
   134  	ikey := i.iter.Key()
   135  	i.samplingGap -= len(ikey) + len(i.iter.Value())
   136  	for i.samplingGap < 0 {
   137  		i.samplingGap += i.db.iterSamplingRate()
   138  		i.db.sampleSeek(ikey)
   139  	}
   140  }
   141  
   142  func (i *dbIter) setErr(err error) {
   143  	i.err = err
   144  	i.key = nil
   145  	i.value = nil
   146  }
   147  
   148  func (i *dbIter) iterErr() {
   149  	if err := i.iter.Error(); err != nil {
   150  		i.setErr(err)
   151  	}
   152  }
   153  
   154  func (i *dbIter) Valid() bool {
   155  	return i.err == nil && i.dir > dirEOI
   156  }
   157  
   158  func (i *dbIter) First() bool {
   159  	if i.err != nil {
   160  		return false
   161  	} else if i.dir == dirReleased {
   162  		i.err = ErrIterReleased
   163  		return false
   164  	}
   165  
   166  	if i.iter.First() {
   167  		i.dir = dirSOI
   168  		return i.next()
   169  	}
   170  	i.dir = dirEOI
   171  	i.iterErr()
   172  	return false
   173  }
   174  
   175  func (i *dbIter) Last() bool {
   176  	if i.err != nil {
   177  		return false
   178  	} else if i.dir == dirReleased {
   179  		i.err = ErrIterReleased
   180  		return false
   181  	}
   182  
   183  	if i.iter.Last() {
   184  		return i.prev()
   185  	}
   186  	i.dir = dirSOI
   187  	i.iterErr()
   188  	return false
   189  }
   190  
   191  func (i *dbIter) Seek(key []byte) bool {
   192  	if i.err != nil {
   193  		return false
   194  	} else if i.dir == dirReleased {
   195  		i.err = ErrIterReleased
   196  		return false
   197  	}
   198  
   199  	ikey := makeInternalKey(nil, key, i.seq, keyTypeSeek)
   200  	if i.iter.Seek(ikey) {
   201  		i.dir = dirSOI
   202  		return i.next()
   203  	}
   204  	i.dir = dirEOI
   205  	i.iterErr()
   206  	return false
   207  }
   208  
   209  func (i *dbIter) next() bool {
   210  	for {
   211  		if ukey, seq, kt, kerr := parseInternalKey(i.iter.Key()); kerr == nil {
   212  			i.sampleSeek()
   213  			if seq <= i.seq {
   214  				switch kt {
   215  				case keyTypeDel:
   216  					// Skip deleted key.
   217  					i.key = append(i.key[:0], ukey...)
   218  					i.dir = dirForward
   219  				case keyTypeVal:
   220  					if i.dir == dirSOI || i.icmp.uCompare(ukey, i.key) > 0 {
   221  						i.key = append(i.key[:0], ukey...)
   222  						i.value = append(i.value[:0], i.iter.Value()...)
   223  						i.dir = dirForward
   224  						return true
   225  					}
   226  				}
   227  			}
   228  		} else if i.strict {
   229  			i.setErr(kerr)
   230  			break
   231  		}
   232  		if !i.iter.Next() {
   233  			i.dir = dirEOI
   234  			i.iterErr()
   235  			break
   236  		}
   237  	}
   238  	return false
   239  }
   240  
   241  func (i *dbIter) Next() bool {
   242  	if i.dir == dirEOI || i.err != nil {
   243  		return false
   244  	} else if i.dir == dirReleased {
   245  		i.err = ErrIterReleased
   246  		return false
   247  	}
   248  
   249  	if !i.iter.Next() || (i.dir == dirBackward && !i.iter.Next()) {
   250  		i.dir = dirEOI
   251  		i.iterErr()
   252  		return false
   253  	}
   254  	return i.next()
   255  }
   256  
   257  func (i *dbIter) prev() bool {
   258  	i.dir = dirBackward
   259  	del := true
   260  	if i.iter.Valid() {
   261  		for {
   262  			if ukey, seq, kt, kerr := parseInternalKey(i.iter.Key()); kerr == nil {
   263  				i.sampleSeek()
   264  				if seq <= i.seq {
   265  					if !del && i.icmp.uCompare(ukey, i.key) < 0 {
   266  						return true
   267  					}
   268  					del = (kt == keyTypeDel)
   269  					if !del {
   270  						i.key = append(i.key[:0], ukey...)
   271  						i.value = append(i.value[:0], i.iter.Value()...)
   272  					}
   273  				}
   274  			} else if i.strict {
   275  				i.setErr(kerr)
   276  				return false
   277  			}
   278  			if !i.iter.Prev() {
   279  				break
   280  			}
   281  		}
   282  	}
   283  	if del {
   284  		i.dir = dirSOI
   285  		i.iterErr()
   286  		return false
   287  	}
   288  	return true
   289  }
   290  
   291  func (i *dbIter) Prev() bool {
   292  	if i.dir == dirSOI || i.err != nil {
   293  		return false
   294  	} else if i.dir == dirReleased {
   295  		i.err = ErrIterReleased
   296  		return false
   297  	}
   298  
   299  	switch i.dir {
   300  	case dirEOI:
   301  		return i.Last()
   302  	case dirForward:
   303  		for i.iter.Prev() {
   304  			if ukey, _, _, kerr := parseInternalKey(i.iter.Key()); kerr == nil {
   305  				i.sampleSeek()
   306  				if i.icmp.uCompare(ukey, i.key) < 0 {
   307  					goto cont
   308  				}
   309  			} else if i.strict {
   310  				i.setErr(kerr)
   311  				return false
   312  			}
   313  		}
   314  		i.dir = dirSOI
   315  		i.iterErr()
   316  		return false
   317  	}
   318  
   319  cont:
   320  	return i.prev()
   321  }
   322  
   323  func (i *dbIter) Key() []byte {
   324  	if i.err != nil || i.dir <= dirEOI {
   325  		return nil
   326  	}
   327  	return i.key
   328  }
   329  
   330  func (i *dbIter) Value() []byte {
   331  	if i.err != nil || i.dir <= dirEOI {
   332  		return nil
   333  	}
   334  	return i.value
   335  }
   336  
   337  func (i *dbIter) Release() {
   338  	if i.dir != dirReleased {
   339  		// Clear the finalizer.
   340  		runtime.SetFinalizer(i, nil)
   341  
   342  		if i.releaser != nil {
   343  			i.releaser.Release()
   344  			i.releaser = nil
   345  		}
   346  
   347  		i.dir = dirReleased
   348  		i.key = nil
   349  		i.value = nil
   350  		i.iter.Release()
   351  		i.iter = nil
   352  		atomic.AddInt32(&i.db.aliveIters, -1)
   353  		i.db = nil
   354  	}
   355  }
   356  
   357  func (i *dbIter) SetReleaser(releaser util.Releaser) {
   358  	if i.dir == dirReleased {
   359  		panic(util.ErrReleased)
   360  	}
   361  	if i.releaser != nil && releaser != nil {
   362  		panic(util.ErrHasReleaser)
   363  	}
   364  	i.releaser = releaser
   365  }
   366  
   367  func (i *dbIter) Error() error {
   368  	return i.err
   369  }