blob: 6639e8d74cc9c9164ea66ad1369e371c5291114b [file] [log] [blame]
// Copyright 2015 The Vanadium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// Package memstore provides a simple, in-memory implementation of store.Store.
// Since it's a prototype implementation, it makes no attempt to be performant.
package memstore
import (
"fmt"
"sync"
"v.io/v23/verror"
"v.io/x/ref/services/syncbase/store"
"v.io/x/ref/services/syncbase/store/ptrie"
"v.io/x/ref/services/syncbase/store/transactions"
)
type memstore struct {
mu sync.Mutex
node *store.ResourceNode
data *ptrie.T
err error
}
// New creates a new memstore.
func New() store.Store {
return transactions.Wrap(&memstore{
node: store.NewResourceNode(),
data: ptrie.New(true),
})
}
// Close implements the store.Store interface.
func (st *memstore) Close() error {
st.mu.Lock()
defer st.mu.Unlock()
if st.err != nil {
return store.ConvertError(st.err)
}
st.node.Close()
st.err = verror.New(verror.ErrCanceled, nil, store.ErrMsgClosedStore)
return nil
}
// Get implements the store.StoreReader interface.
func (st *memstore) Get(key, valbuf []byte) ([]byte, error) {
st.mu.Lock()
defer st.mu.Unlock()
if st.err != nil {
return valbuf, store.ConvertError(st.err)
}
value := st.data.Get(key)
if value == nil {
return valbuf, verror.New(store.ErrUnknownKey, nil, string(key))
}
return store.CopyBytes(valbuf, value.([]byte)), nil
}
// Scan implements the store.StoreReader interface.
func (st *memstore) Scan(start, limit []byte) store.Stream {
st.mu.Lock()
defer st.mu.Unlock()
if st.err != nil {
return &store.InvalidStream{Error: st.err}
}
return newStream(st.data.Copy(), st.node, start, limit)
}
// NewSnapshot implements the store.Store interface.
func (st *memstore) NewSnapshot() store.Snapshot {
st.mu.Lock()
defer st.mu.Unlock()
if st.err != nil {
return &store.InvalidSnapshot{Error: st.err}
}
return newSnapshot(st.data.Copy(), st.node)
}
// WriteBatch implements the transactions.BatchStore interface.
func (st *memstore) WriteBatch(batch ...transactions.WriteOp) error {
st.mu.Lock()
defer st.mu.Unlock()
if st.err != nil {
return store.ConvertError(st.err)
}
for _, write := range batch {
switch write.T {
case transactions.PutOp:
st.data.Put(write.Key, store.CopyBytes(nil, write.Value))
case transactions.DeleteOp:
st.data.Delete(write.Key)
default:
panic(fmt.Sprintf("unknown write operation type: %v", write.T))
}
}
return nil
}