func (p *sessionRecord) readUvarintMayEOF(field string, r io.ByteReader, mayEOF bool) uint64 { if p.err != nil { return 0 } x, err := binary.ReadUvarint(r) if err != nil { if err == io.ErrUnexpectedEOF || (mayEOF == false && err == io.EOF) { p.err = errors.NewErrCorrupted(nil, &ErrManifestCorrupted{field, "short read"}) } else if strings.HasPrefix(err.Error(), "binary:") { p.err = errors.NewErrCorrupted(nil, &ErrManifestCorrupted{field, err.Error()}) } else { p.err = err } return 0 } return x }
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 }
func (p *sessionRecord) readLevel(field string, r io.ByteReader) int { if p.err != nil { return 0 } x := p.readUvarint(field, r) if p.err != nil { return 0 } if x >= uint64(p.numLevel) { p.err = errors.NewErrCorrupted(nil, &ErrManifestCorrupted{field, "invalid level number"}) return 0 } return int(x) }
func (p *sessionRecord) readBytes(field string, r byteReader) []byte { if p.err != nil { return nil } n := p.readUvarint(field, r) if p.err != nil { return nil } x := make([]byte, n) _, p.err = io.ReadFull(r, x) if p.err != nil { if p.err == io.ErrUnexpectedEOF { p.err = errors.NewErrCorrupted(nil, &ErrManifestCorrupted{field, "short read"}) } return nil } return x }
func newErrIkeyCorrupted(ikey []byte, reason string) error { return errors.NewErrCorrupted(nil, &ErrIkeyCorrupted{append([]byte{}, ikey...), reason}) }
func newErrManifestCorrupted(f storage.File, field, reason string) error { return errors.NewErrCorrupted(f, &ErrManifestCorrupted{field, reason}) }
func newErrBatchCorrupted(reason string) error { return errors.NewErrCorrupted(nil, &ErrBatchCorrupted{reason}) }
// Check and clean files. func (db *DB) checkAndCleanFiles() error { v := db.s.version() defer v.release() tablesMap := make(map[uint64]bool) for _, tables := range v.tables { for _, t := range tables { tablesMap[t.file.Num()] = false } } files, err := db.s.getFiles(storage.TypeAll) if err != nil { return err } var nTables int var rem []storage.File for _, f := range files { keep := true switch f.Type() { case storage.TypeManifest: keep = f.Num() >= db.s.manifestFile.Num() case storage.TypeJournal: if db.frozenJournalFile != nil { keep = f.Num() >= db.frozenJournalFile.Num() } else { keep = f.Num() >= db.journalFile.Num() } case storage.TypeTable: _, keep = tablesMap[f.Num()] if keep { tablesMap[f.Num()] = true nTables++ } } if !keep { rem = append(rem, f) } } if nTables != len(tablesMap) { var missing []*storage.FileInfo for num, present := range tablesMap { if !present { missing = append(missing, &storage.FileInfo{Type: storage.TypeTable, Num: num}) db.logf("db@janitor table missing @%d", num) } } return errors.NewErrCorrupted(nil, &errors.ErrMissingFiles{Files: missing}) } db.logf("db@janitor F·%d G·%d", len(files), len(rem)) for _, f := range rem { db.logf("db@janitor removing %s-%d", f.Type(), f.Num()) if err := f.Remove(); err != nil { return err } } return nil }