-
Notifications
You must be signed in to change notification settings - Fork 4
/
local.go
104 lines (91 loc) · 2.33 KB
/
local.go
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
package storage
import (
"bytes"
"io"
"os"
"path/filepath"
"syscall"
"time"
)
// LocalStorage provides access to the local filesystem.
type LocalStorage interface {
Prefix() string
Read(key string) (*os.File, error)
Stat(key string) (os.FileInfo, error)
Delete(key string) error
Write(key string, body io.Reader) (int64, error)
ListFiles(prefix string) ([]os.FileInfo, error)
CheckAccess(prefix string) error
DiskStats() (*DiskStats, error)
}
type localStorage struct {
prefix string
}
func NewLocalStorage(prefix string) LocalStorage {
return &localStorage{
prefix: prefix,
}
}
func (l *localStorage) Prefix() string {
return l.prefix
}
func (l *localStorage) Read(key string) (*os.File, error) {
return os.OpenFile(filepath.Join(l.prefix, key), os.O_RDONLY, 0600)
}
func (l *localStorage) Stat(key string) (os.FileInfo, error) {
return os.Stat(filepath.Join(l.prefix, key))
}
func (l *localStorage) Delete(key string) error {
return os.Remove(filepath.Join(l.prefix, key))
}
func (l *localStorage) Write(key string, body io.Reader) (int64, error) {
f, err := os.OpenFile(filepath.Join(l.prefix, key), os.O_WRONLY|os.O_TRUNC|os.O_CREATE, 0600)
if err != nil {
return 0, err
}
defer f.Close()
return io.Copy(f, body)
}
func (l *localStorage) ListFiles(path string) ([]os.FileInfo, error) {
var infos []os.FileInfo
path = filepath.Join(l.prefix, path)
err := filepath.Walk(path, func(name string, info os.FileInfo, err error) error {
if err != nil {
return err
} else if info.IsDir() {
if path == name {
return nil
}
return filepath.SkipDir
}
infos = append(infos, info)
return nil
})
if err != nil {
return nil, err
}
return infos, nil
}
func (l *localStorage) CheckAccess(path string) error {
body := []byte(time.Now().UTC().String())
key := filepath.Join(path, "_objstore_touch")
_, err := l.Write(key, bytes.NewReader(body))
return err
}
type DiskStats struct {
BytesAll uint64 `json:"bytes_all"`
BytesUsed uint64 `json:"bytes_used"`
BytesFree uint64 `json:"bytes_free"`
}
func (l *localStorage) DiskStats() (*DiskStats, error) {
var fs syscall.Statfs_t
if err := syscall.Statfs(l.prefix, &fs); err != nil {
return nil, err
}
ds := &DiskStats{
BytesAll: fs.Blocks * uint64(fs.Bsize),
BytesFree: fs.Bfree * uint64(fs.Bsize),
}
ds.BytesUsed = ds.BytesAll - ds.BytesFree
return ds, nil
}