func (s *session) setOptions(o *opt.Options) { s.o = &opt.Options{} if o != nil { *s.o = *o } // Alternative filters. if filters := o.GetAltFilters(); len(filters) > 0 { s.o.AltFilters = make([]filter.Filter, len(filters)) for i, filter := range filters { s.o.AltFilters[i] = &iFilter{filter} } } // Block cache. switch o.GetBlockCache() { case nil: s.o.BlockCache = cache.NewLRUCache(opt.DefaultBlockCacheSize) case opt.NoCache: s.o.BlockCache = nil } // Comparer. s.cmp = &iComparer{o.GetComparer()} s.o.Comparer = s.cmp // Filter. if filter := o.GetFilter(); filter != nil { s.o.Filter = &iFilter{filter} } }
func (s *session) setOptions(o *opt.Options) { no := dupOptions(o) // Alternative filters. if filters := o.GetAltFilters(); len(filters) > 0 { no.AltFilters = make([]filter.Filter, len(filters)) for i, filter := range filters { no.AltFilters[i] = &iFilter{filter} } } // Block cache. switch o.GetBlockCache() { case nil: no.BlockCache = cache.NewLRUCache(o.GetBlockCacheSize()) case opt.NoCache: no.BlockCache = nil } // Comparer. s.icmp = &iComparer{o.GetComparer()} no.Comparer = s.icmp // Filter. if filter := o.GetFilter(); filter != nil { no.Filter = &iFilter{filter} } s.o = &cachedOptions{Options: no} s.o.cache() }
func newSession(d desc.Desc, o *opt.Options) *session { s := new(session) s.desc = d s.o = &iOptions{s, o} s.cmp = &iComparer{o.GetComparer()} filter := o.GetFilter() if filter != nil { s.filter = &iFilter{filter} } s.tops = newTableOps(s, s.o.GetMaxOpenFiles()) s.setVersion(&version{s: s}) return s }
func (s *session) setOptions(o *opt.Options) { no := dupOptions(o) // Alternative filters. if filters := o.GetAltFilters(); len(filters) > 0 { no.AltFilters = make([]filter.Filter, len(filters)) for i, filter := range filters { no.AltFilters[i] = &iFilter{filter} } } // Comparer. s.icmp = &iComparer{o.GetComparer()} no.Comparer = s.icmp // Filter. if filter := o.GetFilter(); filter != nil { no.Filter = &iFilter{filter} } s.o = &cachedOptions{Options: no} s.o.cache() }
// NewWriter creates a new initialized table writer for the file. // // Table writer is not safe for concurrent use. func NewWriter(f io.Writer, o *opt.Options) *Writer { w := &Writer{ writer: f, cmp: o.GetComparer(), filter: o.GetFilter(), compression: o.GetCompression(), blockSize: o.GetBlockSize(), comparerScratch: make([]byte, 0), } // data block w.dataBlock.restartInterval = o.GetBlockRestartInterval() // The first 20-bytes are used for encoding block handle. w.dataBlock.scratch = w.scratch[20:] // index block w.indexBlock.restartInterval = 1 w.indexBlock.scratch = w.scratch[20:] // filter block if w.filter != nil { w.filterBlock.generator = w.filter.NewGenerator() w.filterBlock.flush(0) } return w }
// NewReader creates a new initialized table reader for the file. // The cache and bpool is optional and can be nil. // // The returned table reader instance is goroutine-safe. func NewReader(f io.ReaderAt, size int64, cache cache.Namespace, bpool *util.BufferPool, o *opt.Options) *Reader { if bpool == nil { bpool = util.NewBufferPool(o.GetBlockSize() + blockTrailerLen) } r := &Reader{ reader: f, cache: cache, bpool: bpool, cmp: o.GetComparer(), checksum: o.GetStrict(opt.StrictBlockChecksum), strictIter: o.GetStrict(opt.StrictIterator), } if f == nil { r.err = errors.New("leveldb/table: Reader: nil file") return r } if size < footerLen { r.err = errors.New("leveldb/table: Reader: invalid table (file size is too small)") return r } var footer [footerLen]byte if _, err := r.reader.ReadAt(footer[:], size-footerLen); err != nil && err != io.EOF { r.err = fmt.Errorf("leveldb/table: Reader: invalid table (could not read footer): %v", err) } if string(footer[footerLen-len(magic):footerLen]) != magic { r.err = errors.New("leveldb/table: Reader: invalid table (bad magic number)") return r } // Decode the metaindex block handle. metaBH, n := decodeBlockHandle(footer[:]) if n == 0 { r.err = errors.New("leveldb/table: Reader: invalid table (bad metaindex block handle)") return r } // Decode the index block handle. indexBH, n := decodeBlockHandle(footer[n:]) if n == 0 { r.err = errors.New("leveldb/table: Reader: invalid table (bad index block handle)") return r } // Read index block. r.indexBlock, r.err = r.readBlock(indexBH, true) if r.err != nil { return r } // Read metaindex block. metaBlock, err := r.readBlock(metaBH, true) if err != nil { r.err = err return r } // Set data end. r.dataEnd = int64(metaBH.offset) metaIter := metaBlock.newIterator(nil, false, nil) for metaIter.Next() { key := string(metaIter.Key()) if !strings.HasPrefix(key, "filter.") { continue } fn := key[7:] var filter filter.Filter if f0 := o.GetFilter(); f0 != nil && f0.Name() == fn { filter = f0 } else { for _, f0 := range o.GetAltFilters() { if f0.Name() == fn { filter = f0 break } } } if filter != nil { filterBH, n := decodeBlockHandle(metaIter.Value()) if n == 0 { continue } // Update data end. r.dataEnd = int64(filterBH.offset) filterBlock, err := r.readFilterBlock(filterBH, filter) if err != nil { continue } r.filterBlock = filterBlock break } } metaIter.Release() return r }
// 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, fd storage.FileDesc, cache *cache.CacheGetter, bpool *util.BufferPool, o *opt.Options) (*Reader, error) { if f == nil { return nil, errors.New("leveldb/table: nil file") } r := &Reader{ fd: fd, 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 }