OLD | NEW |
---|---|
(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. | |
iannucci
2017/01/07 19:06:17
gtreap
dnj
2017/01/08 03:38:14
Done.
| |
22 func storeEntryCompare(a, b interface{}) int { | |
iannucci
2017/01/07 19:06:17
that's unfortunate :/ no way we can hack up gtreap
dnj
2017/01/08 03:38:14
Yeah we totally could do this. Might be worth dete
| |
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: | |
50 // No more "old" items, use up the rest of "new" and fin ish. | |
51 for r != nil { | |
52 f(r.key, nil, r.value) | |
53 r = newIter.Next() | |
54 } | |
55 return | |
56 | |
57 case r == nil: | |
58 // No more "new" items, use up the rest of "old" and fin ish. | |
59 for l != nil { | |
60 f(l.key, l.value, nil) | |
61 l = oldIter.Next() | |
62 } | |
63 return | |
64 | |
65 default: | |
66 switch bytes.Compare(l.key, r.key) { | |
67 case -1: // l < r | |
68 f(l.key, l.value, nil) | |
69 l = oldIter.Next() | |
70 case 0: // l == r | |
71 f(l.key, l.value, r.value) | |
72 l, r = oldIter.Next(), newIter.Next() | |
73 case 1: // l > r | |
74 f(r.key, nil, r.value) | |
75 r = newIter.Next() | |
76 } | |
77 } | |
78 } | |
79 } | |
80 | |
81 // memStore is a generic interface modeled after treapstore.Store. | |
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 generic interface modeled after treapstore.Collection. | |
99 type memCollection interface { | |
100 Name() string | |
101 Delete(k []byte) | |
102 Get(k []byte) []byte | |
103 MinItem() *storeEntry | |
104 Set(k, v []byte) | |
105 Iterator(pivot []byte) memIterator | |
106 | |
107 IsReadOnly() bool | |
108 } | |
109 | |
110 type memStoreImpl struct { | |
111 s *treapstore.Store | |
112 } | |
113 | |
114 var _ memStore = (*memStoreImpl)(nil) | |
115 | |
116 func (*memStoreImpl) ImATestingSnapshot() {} | |
117 | |
118 func (ms *memStoreImpl) IsReadOnly() bool { return ms.s.IsReadOnly() } | |
119 | |
120 func newMemStore() memStore { | |
121 ret := memStore(&memStoreImpl{treapstore.New()}) | |
122 if *logMemCollectionFolder != "" { | |
123 ret = wrapTracingMemStore(ret) | |
124 } | |
125 return ret | |
126 } | |
127 | |
128 func (ms *memStoreImpl) Snapshot() memStore { | |
129 if ms.s.IsReadOnly() { | |
130 return ms | |
131 } | |
132 return &memStoreImpl{ms.s.Snapshot()} | |
133 } | |
134 | |
135 func (ms *memStoreImpl) GetCollection(name string) memCollection { | |
136 coll := ms.s.GetCollection(name) | |
137 if coll == nil { | |
138 return nil | |
139 } | |
140 return &memCollectionImpl{coll} | |
141 } | |
142 | |
143 func (ms *memStoreImpl) GetOrCreateCollection(name string) memCollection { | |
144 coll := ms.s.GetCollection(name) | |
145 if coll == nil { | |
146 coll = ms.s.CreateCollection(name, storeEntryCompare) | |
147 } | |
148 return &memCollectionImpl{coll} | |
149 } | |
150 | |
151 func (ms *memStoreImpl) GetCollectionNames() []string { return ms.s.GetCollectio nNames() } | |
152 | |
153 type memIteratorImpl struct { | |
154 base *gtreap.Iterator | |
155 } | |
156 | |
157 func (it *memIteratorImpl) Next() *storeEntry { | |
158 v, ok := it.base.Next() | |
159 if !ok { | |
160 return nil | |
161 } | |
162 return v.(*storeEntry) | |
163 } | |
164 | |
165 type memCollectionImpl struct { | |
166 c *treapstore.Collection | |
167 } | |
168 | |
169 var _ memCollection = (*memCollectionImpl)(nil) | |
170 | |
171 func (mc *memCollectionImpl) Name() string { return mc.c.Name() } | |
172 func (mc *memCollectionImpl) IsReadOnly() bool { return mc.c.IsReadOnly() } | |
173 | |
174 func (mc *memCollectionImpl) Get(k []byte) []byte { | |
175 if ent := mc.c.Get(storeKey(k)); ent != nil { | |
176 return ent.(*storeEntry).value | |
177 } | |
178 return nil | |
179 } | |
180 | |
181 func (mc *memCollectionImpl) MinItem() *storeEntry { | |
182 ent, _ := mc.c.Min().(*storeEntry) | |
183 return ent | |
184 } | |
185 | |
186 func (mc *memCollectionImpl) Set(k, v []byte) { mc.c.Put(&storeEntry{k, v}) } | |
187 func (mc *memCollectionImpl) Delete(k []byte) { mc.c.Delete(storeKey(k)) } | |
188 | |
189 func (mc *memCollectionImpl) Iterator(target []byte) memIterator { | |
190 if !mc.c.IsReadOnly() { | |
191 // We prevent this to ensure our internal logic, not because it' s actually | |
192 // an invalid operation. | |
193 panic("attempting to get Iterator from r/w memCollection") | |
194 } | |
195 return &memIteratorImpl{mc.c.Iterator(storeKey(target))} | |
196 } | |
197 | |
198 func storeKey(k []byte) *storeEntry { return &storeEntry{k, nil} } | |
199 | |
200 // nilIterator is a memIterator that begins in a depleted state. | |
201 type nilIterator struct{} | |
202 | |
203 func (it nilIterator) Next() *storeEntry { return nil } | |
204 | |
205 func forEachItem(mc memCollection, cb func(k, v []byte) bool) { | |
206 it := mc.Iterator(nil) | |
207 for ent := it.Next(); ent != nil; ent = it.Next() { | |
208 if !cb(ent.key, ent.value) { | |
209 break | |
210 } | |
211 } | |
212 } | |
OLD | NEW |