func (x singleWriter) Write(p []byte) (int, error) { w := x.w if w.seq != x.seq { return 0, errors.New("leveldb/journal: stale writer") } if w.err != nil { return 0, w.err } n0 := len(p) for len(p) > 0 { // Write a block, if it is full. if w.j == blockSize { w.fillHeader(false) w.writeBlock() if w.err != nil { return 0, w.err } w.first = false } // Copy bytes into the buffer. n := copy(w.buf[w.j:], p) w.j += n p = p[n:] } return n0, nil }
func (x *singleReader) ReadByte() (byte, error) { r := x.r if r.seq != x.seq { return 0, errors.New("leveldb/journal: stale reader") } if x.err != nil { return 0, x.err } if r.err != nil { return 0, r.err } for r.i == r.j { if r.last { return 0, io.EOF } x.err = r.nextChunk(false) if x.err != nil { if x.err == errSkip { x.err = io.ErrUnexpectedEOF } return 0, x.err } } c := r.buf[r.i] r.i++ return c, nil }
func (r *Reader) readFilterBlockCached(bh blockHandle, fillCache bool) (*filterBlock, util.Releaser, error) { if r.cache != nil { var ( err error ch *cache.Handle ) if fillCache { ch = r.cache.Get(bh.offset, func() (size int, value cache.Value) { var b *filterBlock b, err = r.readFilterBlock(bh) if err != nil { return 0, nil } return cap(b.data), b }) } else { ch = r.cache.Get(bh.offset, nil) } if ch != nil { b, ok := ch.Value().(*filterBlock) if !ok { ch.Release() return nil, nil, errors.New("leveldb/table: inconsistent block type") } return b, ch, err } else if err != nil { return nil, nil, err } } b, err := r.readFilterBlock(bh) return b, b, err }
func (x *singleReader) Read(p []byte) (int, error) { r := x.r if r.seq != x.seq { return 0, errors.New("leveldb/journal: stale reader") } if x.err != nil { return 0, x.err } if r.err != nil { return 0, r.err } for r.i == r.j { if r.last { return 0, io.EOF } x.err = r.nextChunk(false) if x.err != nil { if x.err == errSkip { x.err = io.ErrUnexpectedEOF } return 0, x.err } } n := copy(p, r.buf[r.i:r.j]) r.i += n return n, nil }
// Close finishes the current journal and closes the writer. func (w *Writer) Close() error { w.seq++ w.writePending() if w.err != nil { return w.err } w.err = errors.New("leveldb/journal: closed Writer") return nil }
func (r *Reader) newBlockIter(b *block, bReleaser util.Releaser, slice *util.Range, inclLimit bool) *blockIter { bi := &blockIter{ tr: r, block: b, blockReleaser: bReleaser, // Valid key should never be nil. key: make([]byte, 0), dir: dirSOI, riStart: 0, riLimit: b.restartsLen, offsetStart: 0, offsetRealStart: 0, offsetLimit: b.restartsOffset, } if slice != nil { if slice.Start != nil { if bi.Seek(slice.Start) { bi.riStart = b.restartIndex(bi.restartIndex, b.restartsLen, bi.prevOffset) bi.offsetStart = b.restartOffset(bi.riStart) bi.offsetRealStart = bi.prevOffset } else { bi.riStart = b.restartsLen bi.offsetStart = b.restartsOffset bi.offsetRealStart = b.restartsOffset } } if slice.Limit != nil { if bi.Seek(slice.Limit) && (!inclLimit || bi.Next()) { bi.offsetLimit = bi.prevOffset bi.riLimit = bi.restartIndex + 1 } } bi.reset() if bi.offsetStart > bi.offsetLimit { bi.sErr(errors.New("leveldb/table: invalid slice range")) } } return bi }
} // NewReader returns a new reader. The dropper may be nil, and if // strict is true then corrupted or invalid chunk will halt the journal // reader entirely. func NewReader(r io.Reader, dropper Dropper, strict, checksum bool) *Reader { return &Reader{ r: r, dropper: dropper, strict: strict, checksum: checksum, last: true, } } var errSkip = errors.New("leveldb/journal: skipped") func (r *Reader) corrupt(n int, reason string, skip bool) error { if r.dropper != nil { r.dropper.Drop(&ErrCorrupted{n, reason}) } if r.strict && !skip { r.err = errors.NewErrCorrupted(nil, &ErrCorrupted{n, reason}) return r.err } return errSkip } // nextChunk sets r.buf[r.i:r.j] to hold the next chunk's payload, reading the // next block into the buffer if necessary. func (r *Reader) nextChunk(first bool) error {
// Copyright (c) 2014, Suryandaru Triandana <*****@*****.**> // All rights reserved. // // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. package leveldb import ( "github.com/brb/goleveldb/leveldb/errors" ) var ( ErrNotFound = errors.ErrNotFound ErrReadOnly = errors.New("leveldb: read-only mode") ErrSnapshotReleased = errors.New("leveldb: snapshot released") ErrIterReleased = errors.New("leveldb: iterator released") ErrClosed = errors.New("leveldb: closed") )
// Package memdb provides in-memory key/value database implementation. package memdb import ( "math/rand" "sync" "github.com/brb/goleveldb/leveldb/comparer" "github.com/brb/goleveldb/leveldb/errors" "github.com/brb/goleveldb/leveldb/iterator" "github.com/brb/goleveldb/leveldb/util" ) var ( ErrNotFound = errors.ErrNotFound ErrIterReleased = errors.New("leveldb/memdb: iterator released") ) const tMaxHeight = 12 type dbIter struct { util.BasicReleaser p *DB slice *util.Range node int forward bool key, value []byte err error } func (i *dbIter) fill(checkStart, checkLimit bool) bool {
// NewReader creates a new initialized table reader for the file. // The fi, cache and bpool is optional and can be nil. // // The returned table reader instance is goroutine-safe. func NewReader(f io.ReaderAt, size int64, fi *storage.FileInfo, cache *cache.CacheGetter, bpool *util.BufferPool, o *opt.Options) (*Reader, error) { if f == nil { return nil, errors.New("leveldb/table: nil file") } r := &Reader{ fi: fi, reader: f, cache: cache, bpool: bpool, o: o, cmp: o.GetComparer(), verifyChecksum: o.GetStrict(opt.StrictBlockChecksum), } if size < footerLen { r.err = r.newErrCorrupted(0, size, "table", "too small") return r, nil } footerPos := size - footerLen var footer [footerLen]byte if _, err := r.reader.ReadAt(footer[:], footerPos); err != nil && err != io.EOF { return nil, err } if string(footer[footerLen-len(magic):footerLen]) != magic { r.err = r.newErrCorrupted(footerPos, footerLen, "table-footer", "bad magic number") return r, nil } var n int // Decode the metaindex block handle. r.metaBH, n = decodeBlockHandle(footer[:]) if n == 0 { r.err = r.newErrCorrupted(footerPos, footerLen, "table-footer", "bad metaindex block handle") return r, nil } // Decode the index block handle. r.indexBH, n = decodeBlockHandle(footer[n:]) if n == 0 { r.err = r.newErrCorrupted(footerPos, footerLen, "table-footer", "bad index block handle") return r, nil } // Read metaindex block. metaBlock, err := r.readBlock(r.metaBH, true) if err != nil { if errors.IsCorrupted(err) { r.err = err return r, nil } else { return nil, err } } // Set data end. r.dataEnd = int64(r.metaBH.offset) // Read metaindex. metaIter := r.newBlockIter(metaBlock, nil, nil, true) for metaIter.Next() { key := string(metaIter.Key()) if !strings.HasPrefix(key, "filter.") { continue } fn := key[7:] if f0 := o.GetFilter(); f0 != nil && f0.Name() == fn { r.filter = f0 } else { for _, f0 := range o.GetAltFilters() { if f0.Name() == fn { r.filter = f0 break } } } if r.filter != nil { filterBH, n := decodeBlockHandle(metaIter.Value()) if n == 0 { continue } r.filterBH = filterBH // Update data end. r.dataEnd = int64(filterBH.offset) break } } metaIter.Release() metaBlock.Release() // Cache index and filter block locally, since we don't have global cache. if cache == nil { r.indexBlock, err = r.readBlock(r.indexBH, true) if err != nil { if errors.IsCorrupted(err) { r.err = err return r, nil } else { return nil, err } } if r.filter != nil { r.filterBlock, err = r.readFilterBlock(r.filterBH) if err != nil { if !errors.IsCorrupted(err) { return nil, err } // Don't use filter then. r.filter = nil } } } return r, nil }
"github.com/golang/snappy" "github.com/brb/goleveldb/leveldb/cache" "github.com/brb/goleveldb/leveldb/comparer" "github.com/brb/goleveldb/leveldb/errors" "github.com/brb/goleveldb/leveldb/filter" "github.com/brb/goleveldb/leveldb/iterator" "github.com/brb/goleveldb/leveldb/opt" "github.com/brb/goleveldb/leveldb/storage" "github.com/brb/goleveldb/leveldb/util" ) var ( ErrNotFound = errors.ErrNotFound ErrReaderReleased = errors.New("leveldb/table: reader released") ErrIterReleased = errors.New("leveldb/table: iterator released") ) type ErrCorrupted struct { Pos int64 Size int64 Kind string Reason string } func (e *ErrCorrupted) Error() string { return fmt.Sprintf("leveldb/table: corruption on %s (pos=%d): %s", e.Kind, e.Pos, e.Reason) } func max(x, y int) int {
// // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. package leveldb import ( "sync" "time" "github.com/brb/goleveldb/leveldb/errors" "github.com/brb/goleveldb/leveldb/opt" ) var ( errCompactionTransactExiting = errors.New("leveldb: compaction transact exiting") ) type cStats struct { sync.Mutex duration time.Duration read uint64 write uint64 } func (p *cStats) add(n *cStatsStaging) { p.Lock() p.duration += n.duration p.read += n.read p.write += n.write p.Unlock()