blob: 7e3f816f008ef5f6d3eb463a724d412c249bf3a5 [file] [log] [blame]
Adam Sadovskyc18c8ca2015-05-08 18:05:46 -07001// Copyright 2015 The Vanadium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style
3// license that can be found in the LICENSE file.
4
5// Package memstore provides a simple, in-memory implementation of store.Store.
6// Since it's a prototype implementation, it makes no attempt to be performant.
7package memstore
8
9import (
10 "sync"
11
12 "v.io/syncbase/x/ref/services/syncbase/store"
Sergey Rogulenkoa53e60f2015-05-22 11:05:01 -070013 "v.io/v23/verror"
Adam Sadovskyc18c8ca2015-05-08 18:05:46 -070014)
15
16type memstore struct {
17 mu sync.Mutex
Sergey Rogulenko95baa662015-05-22 15:07:06 -070018 node *store.ResourceNode
Adam Sadovskyc18c8ca2015-05-08 18:05:46 -070019 data map[string][]byte
Sergey Rogulenkoa53e60f2015-05-22 11:05:01 -070020 err error
Adam Sadovskyc18c8ca2015-05-08 18:05:46 -070021 // Most recent sequence number handed out.
22 lastSeq uint64
23 // Value of lastSeq at the time of the most recent commit.
24 lastCommitSeq uint64
25}
26
27var _ store.Store = (*memstore)(nil)
28
29// New creates a new memstore.
30func New() store.Store {
Sergey Rogulenko95baa662015-05-22 15:07:06 -070031 return &memstore{
32 data: map[string][]byte{},
33 node: store.NewResourceNode(),
34 }
Adam Sadovskyc18c8ca2015-05-08 18:05:46 -070035}
36
37// Close implements the store.Store interface.
38func (st *memstore) Close() error {
Sergey Rogulenkoa53e60f2015-05-22 11:05:01 -070039 st.mu.Lock()
40 defer st.mu.Unlock()
41 if st.err != nil {
Adam Sadovskya3fc33c2015-06-02 18:44:46 -070042 return convertError(st.err)
Sergey Rogulenkoa53e60f2015-05-22 11:05:01 -070043 }
Sergey Rogulenko95baa662015-05-22 15:07:06 -070044 st.node.Close()
Adam Sadovsky8db74432015-05-29 17:37:32 -070045 st.err = verror.New(verror.ErrCanceled, nil, store.ErrMsgClosedStore)
Adam Sadovskyc18c8ca2015-05-08 18:05:46 -070046 return nil
47}
48
49// Get implements the store.StoreReader interface.
50func (st *memstore) Get(key, valbuf []byte) ([]byte, error) {
51 st.mu.Lock()
52 defer st.mu.Unlock()
Sergey Rogulenkoa53e60f2015-05-22 11:05:01 -070053 if st.err != nil {
Adam Sadovskya3fc33c2015-06-02 18:44:46 -070054 return valbuf, convertError(st.err)
Sergey Rogulenkoa53e60f2015-05-22 11:05:01 -070055 }
Adam Sadovskyc18c8ca2015-05-08 18:05:46 -070056 value, ok := st.data[string(key)]
57 if !ok {
Sergey Rogulenkoa53e60f2015-05-22 11:05:01 -070058 return valbuf, verror.New(store.ErrUnknownKey, nil, string(key))
Adam Sadovskyc18c8ca2015-05-08 18:05:46 -070059 }
60 return store.CopyBytes(valbuf, value), nil
61}
62
63// Scan implements the store.StoreReader interface.
Sergey Rogulenkodef3b302015-05-20 17:33:24 -070064func (st *memstore) Scan(start, limit []byte) store.Stream {
Adam Sadovskyc18c8ca2015-05-08 18:05:46 -070065 st.mu.Lock()
66 defer st.mu.Unlock()
Sergey Rogulenkoa53e60f2015-05-22 11:05:01 -070067 if st.err != nil {
68 return &store.InvalidStream{st.err}
69 }
Adam Sadovsky8db74432015-05-29 17:37:32 -070070 // TODO(sadovsky): Close snapshot once stream is closed or canceled.
Sergey Rogulenko95baa662015-05-22 15:07:06 -070071 return newSnapshot(st, st.node).Scan(start, limit)
Adam Sadovskyc18c8ca2015-05-08 18:05:46 -070072}
73
74// Put implements the store.StoreWriter interface.
75func (st *memstore) Put(key, value []byte) error {
76 return store.RunInTransaction(st, func(st store.StoreReadWriter) error {
77 return st.Put(key, value)
78 })
79}
80
81// Delete implements the store.StoreWriter interface.
82func (st *memstore) Delete(key []byte) error {
83 return store.RunInTransaction(st, func(st store.StoreReadWriter) error {
84 return st.Delete(key)
85 })
86}
87
88// NewTransaction implements the store.Store interface.
89func (st *memstore) NewTransaction() store.Transaction {
90 st.mu.Lock()
91 defer st.mu.Unlock()
Sergey Rogulenkoa53e60f2015-05-22 11:05:01 -070092 if st.err != nil {
93 return &store.InvalidTransaction{st.err}
94 }
Adam Sadovskyc18c8ca2015-05-08 18:05:46 -070095 st.lastSeq++
Sergey Rogulenko95baa662015-05-22 15:07:06 -070096 return newTransaction(st, st.node, st.lastSeq)
Adam Sadovskyc18c8ca2015-05-08 18:05:46 -070097}
98
99// NewSnapshot implements the store.Store interface.
100func (st *memstore) NewSnapshot() store.Snapshot {
101 st.mu.Lock()
102 defer st.mu.Unlock()
Sergey Rogulenkoa53e60f2015-05-22 11:05:01 -0700103 if st.err != nil {
104 return &store.InvalidSnapshot{st.err}
105 }
Sergey Rogulenko95baa662015-05-22 15:07:06 -0700106 return newSnapshot(st, st.node)
Adam Sadovskyc18c8ca2015-05-08 18:05:46 -0700107}