Issues (121)

cache/bolt.go (3 issues)

Severity
1
/* Vuls - Vulnerability Scanner
2
Copyright (C) 2016  Future Corporation , Japan.
3
4
This program is free software: you can redistribute it and/or modify
5
it under the terms of the GNU General Public License as published by
6
the Free Software Foundation, either version 3 of the License, or
7
(at your option) any later version.
8
9
This program is distributed in the hope that it will be useful,
10
but WITHOUT ANY WARRANTY; without even the implied warranty of
11
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12
GNU General Public License for more details.
13
14
You should have received a copy of the GNU General Public License
15
along with this program.  If not, see <http://www.gnu.org/licenses/>.
16
*/
17
18
package cache
19
20
import (
21
	"encoding/json"
22
	"time"
23
24
	"github.com/boltdb/bolt"
25
	"github.com/future-architect/vuls/util"
26
	"github.com/sirupsen/logrus"
27
	"golang.org/x/xerrors"
28
)
29
30
// Bolt holds a pointer of bolt.DB
31
// boltdb is used to store a cache of Changelogs of Ubuntu/Debian
32
type Bolt struct {
33
	Path string
34
	Log  *logrus.Entry
35
	db   *bolt.DB
36
}
37
38
// SetupBolt opens a boltdb and creates a meta bucket if not exists.
39
func SetupBolt(path string, l *logrus.Entry) error {
40
	l.Infof("Open boltDB: %s", path)
41
	db, err := bolt.Open(path, 0600, nil)
42
	if err != nil {
43
		return err
44
	}
45
46
	b := Bolt{
47
		Path: path,
48
		Log:  l,
49
		db:   db,
50
	}
51
	if err = b.createBucketIfNotExists(metabucket); err != nil {
52
		return err
53
	}
54
55
	DB = b
56
	return nil
57
}
58
59
// Close a db.
60
func (b Bolt) Close() error {
61
	if b.db == nil {
62
		return nil
63
	}
64
	return b.db.Close()
65
}
66
67
//  CreateBucketIfNotExists creates a buket that is specified by arg.
68
func (b *Bolt) createBucketIfNotExists(name string) error {
69
	return b.db.Update(func(tx *bolt.Tx) error {
70
		_, err := tx.CreateBucketIfNotExists([]byte(name))
71
		if err != nil {
72
			return xerrors.Errorf("Failed to create bucket: %w", err)
0 ignored issues
show
unrecognized printf verb 'w'
Loading history...
73
		}
74
		return nil
75
	})
76
}
77
78
// GetMeta gets a Meta Information os the servername to boltdb.
79
func (b Bolt) GetMeta(serverName string) (meta Meta, found bool, err error) {
80
	err = b.db.View(func(tx *bolt.Tx) error {
81
		bkt := tx.Bucket([]byte(metabucket))
82
		v := bkt.Get([]byte(serverName))
83
		if len(v) == 0 {
84
			found = false
85
			return nil
86
		}
87
		if e := json.Unmarshal(v, &meta); e != nil {
88
			return e
89
		}
90
		found = true
91
		return nil
92
	})
93
	return
94
}
95
96
// RefreshMeta gets a Meta Information os the servername to boltdb.
97
func (b Bolt) RefreshMeta(meta Meta) error {
98
	meta.CreatedAt = time.Now()
99
	jsonBytes, err := json.Marshal(meta)
100
	if err != nil {
101
		return xerrors.Errorf("Failed to marshal to JSON: %w", err)
0 ignored issues
show
unrecognized printf verb 'w'
Loading history...
102
	}
103
	return b.db.Update(func(tx *bolt.Tx) error {
104
		bkt := tx.Bucket([]byte(metabucket))
105
		if err := bkt.Put([]byte(meta.Name), jsonBytes); err != nil {
106
			return err
107
		}
108
		b.Log.Debugf("Refreshed Meta: %s", meta.Name)
109
		return nil
110
	})
111
}
112
113
// EnsureBuckets puts a Meta information and create a buket that holds changelogs.
114
func (b Bolt) EnsureBuckets(meta Meta) error {
115
	jsonBytes, err := json.Marshal(meta)
116
	if err != nil {
117
		return xerrors.Errorf("Failed to marshal to JSON: %w", err)
0 ignored issues
show
unrecognized printf verb 'w'
Loading history...
118
	}
119
	return b.db.Update(func(tx *bolt.Tx) error {
120
		b.Log.Debugf("Put to meta: %s", meta.Name)
121
		bkt := tx.Bucket([]byte(metabucket))
122
		if err := bkt.Put([]byte(meta.Name), jsonBytes); err != nil {
123
			return err
124
		}
125
126
		// re-create a bucket (bucket name: servername)
127
		bkt = tx.Bucket([]byte(meta.Name))
128
		if bkt != nil {
129
			b.Log.Debugf("Delete bucket: %s", meta.Name)
130
			if err := tx.DeleteBucket([]byte(meta.Name)); err != nil {
131
				return err
132
			}
133
			b.Log.Debugf("Bucket deleted: %s", meta.Name)
134
		}
135
		b.Log.Debugf("Create bucket: %s", meta.Name)
136
		if _, err := tx.CreateBucket([]byte(meta.Name)); err != nil {
137
			return err
138
		}
139
		b.Log.Debugf("Bucket created: %s", meta.Name)
140
		return nil
141
	})
142
}
143
144
// PrettyPrint is for debug
145
func (b Bolt) PrettyPrint(meta Meta) error {
146
	return b.db.View(func(tx *bolt.Tx) error {
147
		bkt := tx.Bucket([]byte(metabucket))
148
		v := bkt.Get([]byte(meta.Name))
149
		b.Log.Debugf("Meta: key:%s, value:%s", meta.Name, v)
150
151
		bkt = tx.Bucket([]byte(meta.Name))
152
		c := bkt.Cursor()
153
		for k, v := c.First(); k != nil; k, v = c.Next() {
154
			b.Log.Debugf("key:%s, len: %d, %s...",
155
				k, len(v), util.Truncate(string(v), 30))
156
		}
157
		return nil
158
	})
159
}
160
161
// GetChangelog get the changelgo of specified packName from the Bucket
162
func (b Bolt) GetChangelog(servername, packName string) (changelog string, err error) {
163
	err = b.db.View(func(tx *bolt.Tx) error {
164
		bkt := tx.Bucket([]byte(servername))
165
		if bkt == nil {
166
			return xerrors.Errorf("Failed to get Bucket: %s", servername)
167
		}
168
		v := bkt.Get([]byte(packName))
169
		if v == nil {
170
			changelog = ""
171
			return nil
172
		}
173
		changelog = string(v)
174
		return nil
175
	})
176
	return
177
}
178
179
// PutChangelog put the changelgo of specified packName into the Bucket
180
func (b Bolt) PutChangelog(servername, packName, changelog string) error {
181
	return b.db.Update(func(tx *bolt.Tx) error {
182
		bkt := tx.Bucket([]byte(servername))
183
		if bkt == nil {
184
			return xerrors.Errorf("Failed to get Bucket: %s", servername)
185
		}
186
		return bkt.Put([]byte(packName), []byte(changelog))
187
	})
188
}
189