Add box to bolt
This commit is contained in:
parent
d7737effbf
commit
3e3ab869d4
222
internal/server/singleprocess/state/box.go
Normal file
222
internal/server/singleprocess/state/box.go
Normal file
@ -0,0 +1,222 @@
|
||||
package state
|
||||
|
||||
import (
|
||||
"github.com/golang/protobuf/proto"
|
||||
"github.com/hashicorp/go-memdb"
|
||||
"github.com/hashicorp/vagrant-plugin-sdk/proto/vagrant_plugin_sdk"
|
||||
"github.com/hashicorp/vagrant/internal/server/proto/vagrant_server"
|
||||
bolt "go.etcd.io/bbolt"
|
||||
)
|
||||
|
||||
var boxBucket = []byte("box")
|
||||
|
||||
func init() {
|
||||
dbBuckets = append(dbBuckets, boxBucket)
|
||||
dbIndexers = append(dbIndexers, (*State).boxIndexInit)
|
||||
schemas = append(schemas, boxIndexSchema)
|
||||
}
|
||||
|
||||
func (s *State) BoxList() ([]*vagrant_plugin_sdk.Ref_Box, error) {
|
||||
memTxn := s.inmem.Txn(false)
|
||||
defer memTxn.Abort()
|
||||
|
||||
return s.boxList(memTxn)
|
||||
}
|
||||
|
||||
func (s *State) BoxDelete(ref *vagrant_plugin_sdk.Ref_Box) error {
|
||||
memTxn := s.inmem.Txn(true)
|
||||
defer memTxn.Abort()
|
||||
|
||||
err := s.db.Update(func(dbTxn *bolt.Tx) error {
|
||||
return s.boxDelete(dbTxn, memTxn, ref)
|
||||
})
|
||||
if err == nil {
|
||||
memTxn.Commit()
|
||||
}
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
func (s *State) BoxGet(ref *vagrant_plugin_sdk.Ref_Box) (*vagrant_server.Box, error) {
|
||||
memTxn := s.inmem.Txn(false)
|
||||
defer memTxn.Abort()
|
||||
|
||||
var result *vagrant_server.Box
|
||||
err := s.db.View(func(dbTxn *bolt.Tx) error {
|
||||
var err error
|
||||
result, err = s.boxGet(dbTxn, memTxn, ref)
|
||||
return err
|
||||
})
|
||||
|
||||
return result, err
|
||||
}
|
||||
|
||||
func (s *State) BoxtPut(box *vagrant_server.Box) error {
|
||||
memTxn := s.inmem.Txn(true)
|
||||
defer memTxn.Abort()
|
||||
|
||||
err := s.db.Update(func(dbTxn *bolt.Tx) error {
|
||||
return s.boxPut(dbTxn, memTxn, box)
|
||||
})
|
||||
if err == nil {
|
||||
memTxn.Commit()
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
func (s *State) boxList(
|
||||
memTxn *memdb.Txn,
|
||||
) (r []*vagrant_plugin_sdk.Ref_Box, err error) {
|
||||
iter, err := memTxn.Get(boxIndexTableName, boxIndexIdIndexName+"_prefix", "")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var result []*vagrant_plugin_sdk.Ref_Box
|
||||
for {
|
||||
next := iter.Next()
|
||||
if next == nil {
|
||||
break
|
||||
}
|
||||
result = append(result, &vagrant_plugin_sdk.Ref_Box{
|
||||
ResourceId: next.(*boxIndexRecord).Id,
|
||||
Name: next.(*boxIndexRecord).Name,
|
||||
Version: next.(*boxIndexRecord).Version,
|
||||
Provider: next.(*boxIndexRecord).Provider,
|
||||
})
|
||||
}
|
||||
|
||||
return result, nil
|
||||
}
|
||||
|
||||
func (s *State) boxDelete(
|
||||
dbTxn *bolt.Tx,
|
||||
memTxn *memdb.Txn,
|
||||
ref *vagrant_plugin_sdk.Ref_Box,
|
||||
) (err error) {
|
||||
// TODO: should references to the box, say in the machine also be deleted?
|
||||
// Delete the box
|
||||
if err = dbTxn.Bucket(boxBucket).Delete(s.boxIdByRef(ref)); err != nil {
|
||||
return
|
||||
}
|
||||
if err = memTxn.Delete(boxIndexTableName, s.newBoxIndexRecordByRef(ref)); err != nil {
|
||||
return
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func (s *State) boxGet(
|
||||
dbTxn *bolt.Tx,
|
||||
memTxn *memdb.Txn,
|
||||
ref *vagrant_plugin_sdk.Ref_Box,
|
||||
) (r *vagrant_server.Box, err error) {
|
||||
var result vagrant_server.Box
|
||||
b := dbTxn.Bucket(boxBucket)
|
||||
return &result, dbGet(b, s.boxIdByRef(ref), &result)
|
||||
}
|
||||
|
||||
func (s *State) boxPut(
|
||||
dbTxn *bolt.Tx,
|
||||
memTxn *memdb.Txn,
|
||||
value *vagrant_server.Box,
|
||||
) (err error) {
|
||||
id := s.boxId(value)
|
||||
b := dbTxn.Bucket(boxBucket)
|
||||
if err = dbPut(b, id, value); err != nil {
|
||||
s.log.Error("failed to store box in db", "box", value, "error", err)
|
||||
return
|
||||
}
|
||||
|
||||
s.log.Trace("indexing box", "box", value)
|
||||
if err = s.boxIndexSet(memTxn, id, value); err != nil {
|
||||
s.log.Error("failed to index box", "box", value, "error", err)
|
||||
return
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
const (
|
||||
boxIndexIdIndexName = "id"
|
||||
boxIndexNameIndexName = "name"
|
||||
boxIndexTableName = "box-index"
|
||||
)
|
||||
|
||||
type boxIndexRecord struct {
|
||||
Id string // Resource ID
|
||||
Name string // Box Name
|
||||
Version string // Box Version
|
||||
Provider string // Box Provider
|
||||
}
|
||||
|
||||
func (s *State) newBoxIndexRecord(b *vagrant_server.Box) *boxIndexRecord {
|
||||
id := b.Name + "-" + b.Version + "-" + b.Provider
|
||||
return &boxIndexRecord{
|
||||
Id: id,
|
||||
Name: b.Name,
|
||||
Version: b.Version,
|
||||
Provider: b.Provider,
|
||||
}
|
||||
}
|
||||
|
||||
func (s *State) boxIndexSet(txn *memdb.Txn, id []byte, value *vagrant_server.Box) error {
|
||||
return txn.Insert(boxIndexTableName, s.newBoxIndexRecord(value))
|
||||
}
|
||||
|
||||
func (s *State) boxIndexInit(dbTxn *bolt.Tx, memTxn *memdb.Txn) error {
|
||||
bucket := dbTxn.Bucket(boxBucket)
|
||||
return bucket.ForEach(func(k, v []byte) error {
|
||||
var value vagrant_server.Box
|
||||
if err := proto.Unmarshal(v, &value); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := s.boxIndexSet(memTxn, k, &value); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
})
|
||||
}
|
||||
|
||||
func boxIndexSchema() *memdb.TableSchema {
|
||||
return &memdb.TableSchema{
|
||||
Name: boxIndexTableName,
|
||||
Indexes: map[string]*memdb.IndexSchema{
|
||||
boxIndexIdIndexName: {
|
||||
Name: boxIndexIdIndexName,
|
||||
AllowMissing: false,
|
||||
Unique: true,
|
||||
Indexer: &memdb.StringFieldIndex{
|
||||
Field: "Id",
|
||||
Lowercase: true,
|
||||
},
|
||||
},
|
||||
boxIndexNameIndexName: {
|
||||
Name: boxIndexNameIndexName,
|
||||
AllowMissing: false,
|
||||
Unique: false,
|
||||
Indexer: &memdb.StringFieldIndex{
|
||||
Field: "Name",
|
||||
Lowercase: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func (s *State) newBoxIndexRecordByRef(ref *vagrant_plugin_sdk.Ref_Box) *boxIndexRecord {
|
||||
return &boxIndexRecord{
|
||||
Id: ref.ResourceId,
|
||||
Name: ref.Name,
|
||||
Version: ref.Version,
|
||||
Provider: ref.Provider,
|
||||
}
|
||||
}
|
||||
|
||||
func (s *State) boxId(b *vagrant_server.Box) []byte {
|
||||
return []byte(b.Id)
|
||||
}
|
||||
|
||||
func (s *State) boxIdByRef(b *vagrant_plugin_sdk.Ref_Box) []byte {
|
||||
return []byte(b.ResourceId)
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user