aboutsummaryrefslogtreecommitdiffstats
path: root/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/db_util.go
blob: a8a2bdf72e173d592b4eba894a2996595cb1af12 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
// 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
}

type Sizes []uint64

// Sum returns sum of the sizes.
func (p Sizes) Sum() (n uint64) {
    for _, s := range p {
        n += s
    }
    return n
}

// 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()

    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 %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
}