Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(407)

Side by Side Diff: impl/memory/memstore.go

Issue 2604943002: impl/memory: Replace gkvlite with "treapstore". (Closed)
Patch Set: Cleaner multiIterate loop. Created 3 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « impl/memory/gkvlite_utils_test.go ('k') | impl/memory/memstore_iter.go » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 // Copyright 2015 The LUCI Authors. All rights reserved.
2 // Use of this source code is governed under the Apache License, Version 2.0
3 // that can be found in the LICENSE file.
4
5 package memory
6
7 import (
8 "bytes"
9
10 "github.com/luci/gae/service/datastore"
11
12 "github.com/luci/gtreap"
13 "github.com/luci/luci-go/common/data/treapstore"
14 )
15
16 type storeEntry struct {
17 key []byte
18 value []byte
19 }
20
21 // storeEntryCompare is a gtrea.Compare function for *storeEntry.
22 func storeEntryCompare(a, b interface{}) int {
23 return bytes.Compare(a.(*storeEntry).key, b.(*storeEntry).key)
24 }
25
26 func memStoreCollide(o, n memCollection, f func(k, ov, nv []byte)) {
27 var oldIter, newIter memIterator
28 if o != nil {
29 if !o.IsReadOnly() {
30 panic("old collection is r/w")
31 }
32 oldIter = o.Iterator(nil)
33 } else {
34 oldIter = nilIterator{}
35 }
36
37 if n != nil {
38 if !n.IsReadOnly() {
39 panic("new collection is r/w")
40 }
41 newIter = n.Iterator(nil)
42 } else {
43 newIter = nilIterator{}
44 }
45
46 l, r := oldIter.Next(), newIter.Next()
47 for {
48 switch {
49 case l == nil && r == nil:
50 return
51
52 case l == nil:
53 f(r.key, nil, r.value)
Vadim Sh. 2016/12/28 01:57:05 nit: this can be micro optimized by avoiding calls
dnj 2016/12/28 02:52:15 I was initially trying to stay as close to the ori
54 r = newIter.Next()
55
56 case r == nil:
57 f(l.key, l.value, nil)
58 l = oldIter.Next()
59
60 default:
61 switch bytes.Compare(l.key, r.key) {
62 case -1: // l < r
63 f(l.key, l.value, nil)
64 l = oldIter.Next()
65 case 0: // l == r
66 f(l.key, l.value, r.value)
67 l, r = oldIter.Next(), newIter.Next()
68 case 1: // l > r
69 f(r.key, nil, r.value)
70 r = newIter.Next()
71 }
72 }
73 }
74 }
75
76 // memStore is a treapstore.Store which will panic for anything which might
77 // otherwise return an error.
78 //
79 // This is reasonable for in-memory Store objects, since the only errors that
80 // should occur happen with file IO on the underlying file (which of course
Vadim Sh. 2016/12/28 01:57:05 the comment is probably stale. There should be no
dnj 2016/12/28 02:52:15 Done.
81 // doesn't exist).
82 type memStore interface {
83 datastore.TestingSnapshot
84
85 GetCollection(name string) memCollection
86 GetCollectionNames() []string
87 GetOrCreateCollection(name string) memCollection
88 Snapshot() memStore
89
90 IsReadOnly() bool
91 }
92
93 // memIterator is an iterator over a memStore's contents.
94 type memIterator interface {
95 Next() *storeEntry
96 }
97
98 // memCollection is a treapstore.Collection which will panic for anything which
99 // might otherwise return an error.
100 //
101 // This is reasonable for in-memory Store objects, since the only errors that
102 // should occur happen with file IO on the underlying file (which of course
103 // doesn't exist.
104 type memCollection interface {
105 Name() string
106 Delete(k []byte)
107 Get(k []byte) []byte
108 MinItem() *storeEntry
109 Set(k, v []byte)
110 Iterator(pivot []byte) memIterator
111
112 IsReadOnly() bool
113 }
114
115 type memStoreImpl struct {
116 s *treapstore.Store
117 }
118
119 var _ memStore = (*memStoreImpl)(nil)
120
121 func (*memStoreImpl) ImATestingSnapshot() {}
122
123 func (ms *memStoreImpl) IsReadOnly() bool { return ms.s.IsReadOnly() }
124
125 func newMemStore() memStore {
126 ret := memStore(&memStoreImpl{treapstore.New(storeEntryCompare)})
127 if *logMemCollectionFolder != "" {
128 ret = wrapTracingMemStore(ret)
129 }
130 return ret
131 }
132
133 func (ms *memStoreImpl) Snapshot() memStore {
134 if ms.s.IsReadOnly() {
135 return ms
136 }
137 return &memStoreImpl{ms.s.Snapshot()}
138 }
139
140 func (ms *memStoreImpl) GetCollection(name string) memCollection {
141 coll := ms.s.GetCollection(name)
142 if coll == nil {
143 return nil
144 }
145 return &memCollectionImpl{coll}
146 }
147
148 func (ms *memStoreImpl) GetOrCreateCollection(name string) memCollection {
149 return &memCollectionImpl{ms.s.GetOrCreateCollection(name)}
150 }
151
152 func (ms *memStoreImpl) GetCollectionNames() []string { return ms.s.GetCollectio nNames() }
153
154 type memIteratorImpl struct {
155 base *gtreap.Iterator
156 }
157
158 func (it *memIteratorImpl) Next() *storeEntry {
159 v, ok := it.base.Next()
160 if !ok {
161 return nil
162 }
163 return v.(*storeEntry)
164 }
165
166 type memCollectionImpl struct {
167 c *treapstore.Collection
168 }
169
170 var _ memCollection = (*memCollectionImpl)(nil)
171
172 func (mc *memCollectionImpl) Name() string { return mc.c.Name() }
173 func (mc *memCollectionImpl) IsReadOnly() bool { return mc.c.IsReadOnly() }
174
175 func (mc *memCollectionImpl) Get(k []byte) []byte {
176 if ent := mc.c.Get(storeKey(k)); ent != nil {
177 return ent.(*storeEntry).value
178 }
179 return nil
180 }
181
182 func (mc *memCollectionImpl) MinItem() *storeEntry {
183 ent, _ := mc.c.Min().(*storeEntry)
184 return ent
185 }
186
187 func (mc *memCollectionImpl) Set(k, v []byte) { mc.c.Put(&storeEntry{k, v}) }
188 func (mc *memCollectionImpl) Delete(k []byte) { mc.c.Delete(storeKey(k)) }
189
190 func (mc *memCollectionImpl) Iterator(target []byte) memIterator {
191 if !mc.c.IsReadOnly() {
192 // We prevent this to ensure our internal logic, not because it' s actually
193 // an invalid operation.
194 panic("attempting to get Iterator from r/w memCollection")
195 }
196 return &memIteratorImpl{mc.c.Iterator(storeKey(target))}
197 }
198
199 func storeKey(k []byte) *storeEntry { return &storeEntry{k, nil} }
200
201 // nilIterator is a memIterator that begins in a depleted state.
202 type nilIterator struct{}
203
204 func (it nilIterator) Next() *storeEntry { return nil }
205
206 func forEachItem(mc memCollection, cb func(k, v []byte) bool) {
207 it := mc.Iterator(nil)
208 for ent := it.Next(); ent != nil; ent = it.Next() {
209 if !cb(ent.key, ent.value) {
210 break
211 }
212 }
213 }
OLDNEW
« no previous file with comments | « impl/memory/gkvlite_utils_test.go ('k') | impl/memory/memstore_iter.go » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698