// Opens table. It returns a cache handle, which should // be released after use. func (t *tOps) open(f *tFile) (ch *cache.Handle, err error) { ch = t.cache.Get(0, uint64(f.fd.Num), func() (size int, value cache.Value) { var r storage.Reader r, err = t.s.stor.Open(f.fd) if err != nil { return 0, nil } var bcache *cache.NamespaceGetter if t.bcache != nil { bcache = &cache.NamespaceGetter{Cache: t.bcache, NS: uint64(f.fd.Num)} } var tr *table.Reader tr, err = table.NewReader(r, f.size, f.fd, bcache, t.bpool, t.s.o.Options) if err != nil { r.Close() return 0, nil } return 1, tr }) if ch == nil && err == nil { err = ErrClosed } return }
func (t *tOps) lookup(f *tFile) (c cache.Object, err error) { num := f.file.Num() c, ok := t.cacheNS.Get(num, func() (ok bool, value interface{}, charge int, fin cache.SetFin) { var r storage.Reader r, err = f.file.Open() if err != nil { return } o := t.s.o var cacheNS cache.Namespace if bc := o.GetBlockCache(); bc != nil { cacheNS = bc.GetNamespace(num) } ok = true value = table.NewReader(r, int64(f.size), cacheNS, o) charge = 1 fin = func() { r.Close() } return }) if !ok && err == nil { err = ErrClosed } return }
// Opens table. It returns a cache handle, which should // be released after use. func (t *tOps) open(f *tFile) (ch *cache.Handle, err error) { num := f.file.Num() ch = t.cache.Get(0, num, func() (size int, value cache.Value) { var r storage.Reader r, err = f.file.Open() if err != nil { return 0, nil } var bcache *cache.CacheGetter if t.bcache != nil { bcache = &cache.CacheGetter{Cache: t.bcache, NS: num} } var tr *table.Reader tr, err = table.NewReader(r, int64(f.size), storage.NewFileInfo(f.file), bcache, t.bpool, t.s.o.Options) if err != nil { r.Close() return 0, nil } return 1, tr }) if ch == nil && err == nil { err = ErrClosed } return }
// Opens table. It returns a cache handle, which should // be released after use. func (t *tOps) open(f *tFile) (ch cache.Handle, err error) { num := f.file.Num() ch = t.cacheNS.Get(num, func() (charge int, value interface{}) { var r storage.Reader r, err = f.file.Open() if err != nil { return 0, nil } var bcacheNS cache.Namespace if bc := t.s.o.GetBlockCache(); bc != nil { bcacheNS = bc.GetNamespace(num) } var tr *table.Reader tr, err = table.NewReader(r, int64(f.size), storage.NewFileInfo(f.file), bcacheNS, t.bpool, t.s.o.Options) if err != nil { r.Close() return 0, nil } return 1, tr }) if ch == nil && err == nil { err = ErrClosed } return }
func (t *tOps) lookup(f *tFile) (c cache.Object, err error) { num := f.file.Num() c, _ = t.cachens.Get(num, func() (ok bool, value interface{}, charge int, fin func()) { var r storage.Reader r, err = f.file.Open() if err != nil { return } o := t.s.o var ns cache.Namespace bc := o.GetBlockCache() if bc != nil { ns = bc.GetNamespace(num) } var p *table.Reader p, err = table.NewReader(r, f.size, t.s.o, ns) if err != nil { return } ok = true value = p charge = 1 fin = func() { r.Close() } return }) return }
// Recover recovers and opens a DB with missing or corrupted manifest files // for the given storage. It will ignore any manifest files, valid or not. // The DB must already exist or it will returns an error. // Also, Recover will ignore ErrorIfMissing and ErrorIfExist options. // // The DB must be closed after use, by calling Close method. func Recover(p storage.Storage, o *opt.Options) (db *DB, err error) { s, err := newSession(p, o) if err != nil { return } defer func() { if err != nil { s.close() s.release() } }() // get all files ff0, err := s.getFiles(storage.TypeAll) if err != nil { return } ff := files(ff0) ff.sort() s.logf("db@recovery F·%d", len(ff)) rec := new(sessionRecord) // recover tables var nt *tFile for _, f := range ff { if f.Type() != storage.TypeTable { continue } var r storage.Reader r, err = f.Open() if err != nil { return } var size int64 size, err = r.Seek(0, 2) r.Close() if err != nil { return } t := newTFile(f, uint64(size), nil, nil) iter := s.tops.newIterator(t, nil, nil) // min ikey if iter.First() { t.min = iter.Key() } else { err = iter.Error() iter.Release() if err != nil { return } else { continue } } // max ikey if iter.Last() { t.max = iter.Key() } else { err = iter.Error() iter.Release() if err != nil { return } else { continue } } iter.Release() s.logf("db@recovery found table @%d S·%s %q:%q", t.file.Num(), shortenb(int(t.size)), t.min, t.max) // add table to level 0 rec.addTableFile(0, t) nt = t } // extract largest seq number from newest table if nt != nil { var lseq uint64 iter := s.tops.newIterator(nt, nil, nil) for iter.Next() { seq, _, ok := iKey(iter.Key()).parseNum() if !ok { continue } if seq > lseq { lseq = seq } } iter.Release() rec.setSeq(lseq) } // set file num based on largest one if len(ff) > 0 { s.stFileNum = ff[len(ff)-1].Num() + 1 } else { s.stFileNum = 0 } // create brand new manifest err = s.create() if err != nil { return } // commit record err = s.commit(rec) if err != nil { return } return openDB(s) }