102 lines
2.4 KiB
Go
102 lines
2.4 KiB
Go
// Copyright (c) 2012, Suryandaru Triandana <syndtr@gmail.com>
|
|
// 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/syndtr/goleveldb/leveldb/errors"
|
|
"github.com/syndtr/goleveldb/leveldb/iterator"
|
|
"github.com/syndtr/goleveldb/leveldb/opt"
|
|
"github.com/syndtr/goleveldb/leveldb/storage"
|
|
"github.com/syndtr/goleveldb/leveldb/util"
|
|
)
|
|
|
|
// Reader is the interface that wraps basic Get and NewIterator methods.
|
|
// This interface implemented by both DB and Snapshot.
|
|
type Reader interface {
|
|
Get(key []byte, ro *opt.ReadOptions) (value []byte, err error)
|
|
NewIterator(slice *util.Range, ro *opt.ReadOptions) iterator.Iterator
|
|
}
|
|
|
|
// Sizes is list of size.
|
|
type Sizes []int64
|
|
|
|
// Sum returns sum of the sizes.
|
|
func (sizes Sizes) Sum() int64 {
|
|
var sum int64
|
|
for _, size := range sizes {
|
|
sum += size
|
|
}
|
|
return sum
|
|
}
|
|
|
|
// Logging.
|
|
func (db *DB) log(v ...interface{}) { db.s.log(v...) }
|
|
func (db *DB) logf(format string, v ...interface{}) { db.s.logf(format, v...) }
|
|
|
|
// Check and clean files.
|
|
func (db *DB) checkAndCleanFiles() error {
|
|
v := db.s.version()
|
|
defer v.release()
|
|
|
|
tmap := make(map[int64]bool)
|
|
for _, tables := range v.levels {
|
|
for _, t := range tables {
|
|
tmap[t.fd.Num] = false
|
|
}
|
|
}
|
|
|
|
fds, err := db.s.stor.List(storage.TypeAll)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
var nt int
|
|
var rem []storage.FileDesc
|
|
for _, fd := range fds {
|
|
keep := true
|
|
switch fd.Type {
|
|
case storage.TypeManifest:
|
|
keep = fd.Num >= db.s.manifestFd.Num
|
|
case storage.TypeJournal:
|
|
if !db.frozenJournalFd.Zero() {
|
|
keep = fd.Num >= db.frozenJournalFd.Num
|
|
} else {
|
|
keep = fd.Num >= db.journalFd.Num
|
|
}
|
|
case storage.TypeTable:
|
|
_, keep = tmap[fd.Num]
|
|
if keep {
|
|
tmap[fd.Num] = true
|
|
nt++
|
|
}
|
|
}
|
|
|
|
if !keep {
|
|
rem = append(rem, fd)
|
|
}
|
|
}
|
|
|
|
if nt != len(tmap) {
|
|
var mfds []storage.FileDesc
|
|
for num, present := range tmap {
|
|
if !present {
|
|
mfds = append(mfds, storage.FileDesc{Type: storage.TypeTable, Num: num})
|
|
db.logf("db@janitor table missing @%d", num)
|
|
}
|
|
}
|
|
return errors.NewErrCorrupted(storage.FileDesc{}, &errors.ErrMissingFiles{Fds: mfds})
|
|
}
|
|
|
|
db.logf("db@janitor F·%d G·%d", len(fds), len(rem))
|
|
for _, fd := range rem {
|
|
db.logf("db@janitor removing %s-%d", fd.Type, fd.Num)
|
|
if err := db.s.stor.Remove(fd); err != nil {
|
|
return err
|
|
}
|
|
}
|
|
return nil
|
|
}
|