-
Notifications
You must be signed in to change notification settings - Fork 1
/
manager.go
151 lines (119 loc) · 2.9 KB
/
manager.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
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
package manager
import (
"fmt"
"io"
"io/ioutil"
"net/url"
"os"
"sync"
"time"
"github.com/paddlesteamer/hdn-drv/config"
"github.com/paddlesteamer/hdn-drv/db"
"github.com/paddlesteamer/hdn-drv/drive"
)
type dbStat struct {
extFilePath string
extDrive drive.Drive
dbPath string
hash string
mux sync.RWMutex
}
type Manager struct {
drives []drive.Drive
key string
db dbStat
}
const checkInterval time.Duration = 5 * time.Second
func NewManager(conf *config.Configuration) (*Manager, error) {
key := conf.EncryptionKey
drives := []drive.Drive{}
if conf.Dropbox != nil {
dbx := drive.NewDropboxClient(conf.Dropbox)
drives = append(drives, dbx)
}
u, err := url.Parse(conf.DatabaseFile)
if err != nil {
return nil, fmt.Errorf("manager: unable to parse database file url: %v", err)
}
var drv drive.Drive = nil
for _, d := range drives {
if d.GetProviderName() == u.Scheme {
drv = d
break
}
}
if drv == nil {
return nil, fmt.Errorf("manager: couldn't find a drive matching database file scheme")
}
dbf, err := ioutil.TempFile("/tmp", "hdn-drv-db")
if err != nil {
return nil, fmt.Errorf("manager: unable to create database file: %v", err)
}
// defer dbf.Close() close manually, at least shouldn't be deferred here
dbExtPath := fmt.Sprintf("/%s", u.Host)
dbPath := dbf.Name()
_, dbr, err := drv.GetFile(u.Host)
if err != nil { // TODO: check specific 'not found' error
// below is for not found error
dbf.Close()
err = db.InitDB(dbPath)
if err != nil {
return nil, fmt.Errorf("manager: unable to initialize db: %v", err)
}
dbf, err := os.Open(dbPath)
if err != nil {
os.Remove(dbPath)
return nil, fmt.Errorf("manager: unable to open intitialized db: %v", err)
}
defer dbf.Close()
err = drv.PutFile(dbExtPath, dbf)
if err != nil {
os.Remove(dbPath)
return nil, fmt.Errorf("manager: unable to upload initialiezed db: %v", err)
}
} else {
defer dbr.Close()
defer dbf.Close()
_, err := io.Copy(dbf, dbr)
if err != nil {
os.Remove(dbPath)
return nil, fmt.Errorf("manager: unable to copy contents of db to local file: %v", err)
}
}
hash, err := drv.ComputeHash(dbPath)
if err != nil {
os.Remove(dbPath)
return nil, fmt.Errorf("manager: unable to compute hash: %v", err)
}
db := dbStat{
extDrive: drv,
extFilePath: dbExtPath,
dbPath: dbPath,
hash: hash,
}
m := &Manager{
drives: drives,
key: key,
db: db,
}
go m.checkChanges()
return m, nil
}
func (m *Manager) Close() {
os.Remove(m.db.dbPath)
}
func (m *Manager) checkChanges() {
for {
time.Sleep(checkInterval)
mdata, err := m.db.extDrive.GetFileMetadata(m.db.extFilePath)
if err != nil {
fmt.Printf("manager: %v\n", err)
continue
}
if mdata.Hash != m.db.hash {
fmt.Printf("Different hash %v %v\n", mdata.Hash, m.db.hash)
} else {
fmt.Printf("Hashes are same: %v\n", mdata.Hash)
}
}
}