/usr/share/gocode/src/github.com/influxdata/influxdb/cmd/influx_tsm/tsdb/database.go is in golang-github-influxdb-influxdb-dev 1.1.1+dfsg1-4.
This file is owned by root:root, with mode 0o644.
The actual contents of the file can be viewed below.
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 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 | package tsdb // import "github.com/influxdata/influxdb/cmd/influx_tsm/tsdb"
import (
"fmt"
"os"
"path"
"path/filepath"
"sort"
"time"
"github.com/boltdb/bolt"
"github.com/influxdata/influxdb/pkg/slices"
)
// Flags for differentiating between engines
const (
B1 = iota
BZ1
TSM1
)
// EngineFormat holds the flag for the engine
type EngineFormat int
// String returns the string format of the engine.
func (e EngineFormat) String() string {
switch e {
case TSM1:
return "tsm1"
case B1:
return "b1"
case BZ1:
return "bz1"
default:
panic("unrecognized shard engine format")
}
}
// ShardInfo is the description of a shard on disk.
type ShardInfo struct {
Database string
RetentionPolicy string
Path string
Format EngineFormat
Size int64
}
// FormatAsString returns the format of the shard as a string.
func (s *ShardInfo) FormatAsString() string {
return s.Format.String()
}
// FullPath returns the full path to the shard, given the data directory root.
func (s *ShardInfo) FullPath(dataPath string) string {
return filepath.Join(dataPath, s.Database, s.RetentionPolicy, s.Path)
}
// ShardInfos is an array of ShardInfo
type ShardInfos []*ShardInfo
func (s ShardInfos) Len() int { return len(s) }
func (s ShardInfos) Swap(i, j int) { s[i], s[j] = s[j], s[i] }
func (s ShardInfos) Less(i, j int) bool {
if s[i].Database == s[j].Database {
if s[i].RetentionPolicy == s[j].RetentionPolicy {
return s[i].Path < s[i].Path
}
return s[i].RetentionPolicy < s[j].RetentionPolicy
}
return s[i].Database < s[j].Database
}
// Databases returns the sorted unique set of databases for the shards.
func (s ShardInfos) Databases() []string {
dbm := make(map[string]bool)
for _, ss := range s {
dbm[ss.Database] = true
}
var dbs []string
for k := range dbm {
dbs = append(dbs, k)
}
sort.Strings(dbs)
return dbs
}
// FilterFormat returns a copy of the ShardInfos, with shards of the given
// format removed.
func (s ShardInfos) FilterFormat(fmt EngineFormat) ShardInfos {
var a ShardInfos
for _, si := range s {
if si.Format != fmt {
a = append(a, si)
}
}
return a
}
// Size returns the space on disk consumed by the shards.
func (s ShardInfos) Size() int64 {
var sz int64
for _, si := range s {
sz += si.Size
}
return sz
}
// ExclusiveDatabases returns a copy of the ShardInfo, with shards associated
// with the given databases present. If the given set is empty, all databases
// are returned.
func (s ShardInfos) ExclusiveDatabases(exc []string) ShardInfos {
var a ShardInfos
// Empty set? Return everything.
if len(exc) == 0 {
a = make(ShardInfos, len(s))
copy(a, s)
return a
}
for _, si := range s {
if slices.Exists(exc, si.Database) {
a = append(a, si)
}
}
return a
}
// Database represents an entire database on disk.
type Database struct {
path string
}
// NewDatabase creates a database instance using data at path.
func NewDatabase(path string) *Database {
return &Database{path: path}
}
// Name returns the name of the database.
func (d *Database) Name() string {
return path.Base(d.path)
}
// Path returns the path to the database.
func (d *Database) Path() string {
return d.path
}
// Shards returns information for every shard in the database.
func (d *Database) Shards() ([]*ShardInfo, error) {
fd, err := os.Open(d.path)
if err != nil {
return nil, err
}
// Get each retention policy.
rps, err := fd.Readdirnames(-1)
if err != nil {
return nil, err
}
// Process each retention policy.
var shardInfos []*ShardInfo
for _, rp := range rps {
rpfd, err := os.Open(filepath.Join(d.path, rp))
if err != nil {
return nil, err
}
// Process each shard
shards, err := rpfd.Readdirnames(-1)
for _, sh := range shards {
fmt, sz, err := shardFormat(filepath.Join(d.path, rp, sh))
if err != nil {
return nil, err
}
si := &ShardInfo{
Database: d.Name(),
RetentionPolicy: path.Base(rp),
Path: sh,
Format: fmt,
Size: sz,
}
shardInfos = append(shardInfos, si)
}
}
sort.Sort(ShardInfos(shardInfos))
return shardInfos, nil
}
// shardFormat returns the format and size on disk of the shard at path.
func shardFormat(path string) (EngineFormat, int64, error) {
// If it's a directory then it's a tsm1 engine
fi, err := os.Stat(path)
if err != nil {
return 0, 0, err
}
if fi.Mode().IsDir() {
return TSM1, fi.Size(), nil
}
// It must be a BoltDB-based engine.
db, err := bolt.Open(path, 0666, &bolt.Options{Timeout: 1 * time.Second})
if err != nil {
return 0, 0, err
}
defer db.Close()
var format EngineFormat
err = db.View(func(tx *bolt.Tx) error {
// Retrieve the meta bucket.
b := tx.Bucket([]byte("meta"))
// If no format is specified then it must be an original b1 database.
if b == nil {
format = B1
return nil
}
// There is an actual format indicator.
switch f := string(b.Get([]byte("format"))); f {
case "b1", "v1":
format = B1
case "bz1":
format = BZ1
default:
return fmt.Errorf("unrecognized engine format: %s", f)
}
return nil
})
return format, fi.Size(), err
}
|