docs/server/storage/memory.go

112 lines
2.6 KiB
Go

package storage
import (
"fmt"
"strings"
"sync"
"github.com/endophage/gotuf/data"
)
type key struct {
algorithm data.KeyAlgorithm
public []byte
}
type ver struct {
version int
data []byte
}
// MemStorage is really just designed for dev and testing. It is very
// inefficient in many scenarios
type MemStorage struct {
lock sync.Mutex
tufMeta map[string][]*ver
tsKeys map[string]*key
}
// NewMemStorage instantiates a memStorage instance
func NewMemStorage() *MemStorage {
return &MemStorage{
tufMeta: make(map[string][]*ver),
tsKeys: make(map[string]*key),
}
}
// UpdateCurrent updates the meta data for a specific role
func (st *MemStorage) UpdateCurrent(gun string, update MetaUpdate) error {
id := entryKey(gun, update.Role)
st.lock.Lock()
defer st.lock.Unlock()
if space, ok := st.tufMeta[id]; ok {
for _, v := range space {
if v.version >= update.Version {
return &ErrOldVersion{}
}
}
}
st.tufMeta[id] = append(st.tufMeta[id], &ver{version: update.Version, data: update.Data})
return nil
}
// UpdateMany updates multiple TUF records
func (st *MemStorage) UpdateMany(gun string, updates []MetaUpdate) error {
for _, u := range updates {
st.UpdateCurrent(gun, u)
}
return nil
}
// GetCurrent returns the metadada for a given role, under a GUN
func (st *MemStorage) GetCurrent(gun, role string) (data []byte, err error) {
id := entryKey(gun, role)
st.lock.Lock()
defer st.lock.Unlock()
space, ok := st.tufMeta[id]
if !ok || len(space) == 0 {
return nil, &ErrNotFound{}
}
return space[len(space)-1].data, nil
}
// Delete delets all the metadata for a given GUN
func (st *MemStorage) Delete(gun string) error {
st.lock.Lock()
defer st.lock.Unlock()
for k := range st.tufMeta {
if strings.HasPrefix(k, gun) {
delete(st.tufMeta, k)
}
}
return nil
}
// GetTimestampKey returns the public key material of the timestamp key of a given gun
func (st *MemStorage) GetTimestampKey(gun string) (algorithm data.KeyAlgorithm, public []byte, err error) {
// no need for lock. It's ok to return nil if an update
// wasn't observed
k, ok := st.tsKeys[gun]
if !ok {
return "", nil, &ErrNoKey{gun: gun}
}
return k.algorithm, k.public, nil
}
// SetTimestampKey sets a Timestamp key under a gun
func (st *MemStorage) SetTimestampKey(gun string, algorithm data.KeyAlgorithm, public []byte) error {
k := &key{algorithm: algorithm, public: public}
st.lock.Lock()
defer st.lock.Unlock()
if _, ok := st.tsKeys[gun]; ok {
return &ErrTimestampKeyExists{gun: gun}
}
st.tsKeys[gun] = k
return nil
}
func entryKey(gun, role string) string {
return fmt.Sprintf("%s.%s", gun, role)
}