// Recover recover database with missing or corrupted manifest file. It will // ignore any manifest files, valid or not. func Recover(d desc.Desc, o *opt.Options) (db *DB, err error) { s := newSession(d, o) // get all files ff := files(s.getFiles(desc.TypeAll)) ff.sort() s.printf("Recover: started, files=%d", len(ff)) rec := new(sessionRecord) // recover tables ro := &opt.ReadOptions{} var nt *tFile for _, f := range ff { if f.Type() != desc.TypeTable { continue } var size uint64 size, err = f.Size() if err != nil { return } t := newTFile(f, size, nil, nil) iter := s.tops.newIterator(t, ro) // min ikey if iter.First() { t.min = iter.Key() } else if iter.Error() != nil { err = iter.Error() return } else { continue } // max ikey if iter.Last() { t.max = iter.Key() } else if iter.Error() != nil { err = iter.Error() return } else { continue } // 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, ro) for iter.Next() { seq, _, ok := iKey(iter.Key()).parseNum() if !ok { continue } if seq > lseq { lseq = seq } } rec.setSeq(lseq) } // set file num based on largest one s.stFileNum = ff[len(ff)-1].Num() + 1 // create brand new manifest err = s.create() if err != nil { return } // commit record err = s.commit(rec) if err != nil { return } return open(s) }
// NewReader create new initialized table reader. func NewReader(r desc.Reader, size uint64, o opt.OptionsGetter, cache cache.Namespace) (p *Reader, err error) { mb, ib, err := readFooter(r, size) if err != nil { return } t := &Reader{r: r, o: o, dataEnd: mb.offset, cache: cache} // index block buf, err := ib.readAll(r, true) if err != nil { return } t.index, err = block.NewReader(buf, o.GetComparer()) if err != nil { return } // filter block filter := o.GetFilter() if filter != nil { // we will ignore any errors at meta/filter block // since it is not essential for operation // meta block buf, err = mb.readAll(r, true) if err != nil { goto out } var meta *block.Reader meta, err = block.NewReader(buf, comparer.BytesComparer{}) if err != nil { goto out } // check for filter name iter := meta.NewIterator() key := "filter." + filter.Name() if iter.Seek([]byte(key)) && string(iter.Key()) == key { fb := new(bInfo) _, err = fb.decodeFrom(iter.Value()) if err != nil { return } // now the data end before filter block start offset t.dataEnd = fb.offset // filter block buf, err = fb.readAll(r, true) if err != nil { goto out } t.filter, err = block.NewFilterReader(buf, filter) if err != nil { goto out } } } out: return t, nil }