OLD | NEW |
---|---|
1 // Copyright 2015 The Chromium Authors. All rights reserved. | 1 // Copyright 2015 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 package memory | 5 package memory |
6 | 6 |
7 import ( | 7 import ( |
8 "bytes" | 8 "bytes" |
9 "runtime" | 9 "runtime" |
10 "sync" | 10 "sync" |
11 | 11 |
12 "github.com/luci/gae/service/datastore" | |
12 "github.com/luci/gkvlite" | 13 "github.com/luci/gkvlite" |
13 ) | 14 ) |
14 | 15 |
15 func gkvCollide(o, n *memCollection, f func(k, ov, nv []byte)) { | 16 func gkvCollide(o, n memCollection, f func(k, ov, nv []byte)) { |
17 » if o != nil && !o.IsReadOnly() { | |
18 » » panic("gkvCollide: old collection is rw") | |
dnj
2016/04/22 06:09:45
nit: not sure if you need "gkvCollide" prefix here
iannucci
2016/04/22 06:56:25
Done.
| |
19 » } | |
20 » if n != nil && !n.IsReadOnly() { | |
21 » » panic("gkvCollide: new collection is rw") | |
22 » } | |
23 | |
16 // TODO(riannucci): reimplement in terms of *iterator. | 24 // TODO(riannucci): reimplement in terms of *iterator. |
17 oldItems, newItems := make(chan *gkvlite.Item), make(chan *gkvlite.Item) | 25 oldItems, newItems := make(chan *gkvlite.Item), make(chan *gkvlite.Item) |
18 » walker := func(c *memCollection, ch chan<- *gkvlite.Item, wg *sync.WaitG roup) { | 26 » walker := func(c memCollection, ch chan<- *gkvlite.Item, wg *sync.WaitGr oup) { |
19 defer close(ch) | 27 defer close(ch) |
20 defer wg.Done() | 28 defer wg.Done() |
21 if c != nil { | 29 if c != nil { |
22 c.VisitItemsAscend(nil, true, func(i *gkvlite.Item) bool { | 30 c.VisitItemsAscend(nil, true, func(i *gkvlite.Item) bool { |
23 ch <- i | 31 ch <- i |
24 return true | 32 return true |
25 }) | 33 }) |
26 } | 34 } |
27 } | 35 } |
28 | 36 |
(...skipping 30 matching lines...) Expand all Loading... | |
59 } | 67 } |
60 wg.Wait() | 68 wg.Wait() |
61 } | 69 } |
62 | 70 |
63 // memStore is a gkvlite.Store which will panic for anything which might | 71 // memStore is a gkvlite.Store which will panic for anything which might |
64 // otherwise return an error. | 72 // otherwise return an error. |
65 // | 73 // |
66 // This is reasonable for in-memory Store objects, since the only errors that | 74 // This is reasonable for in-memory Store objects, since the only errors that |
67 // should occur happen with file IO on the underlying file (which of course | 75 // should occur happen with file IO on the underlying file (which of course |
68 // doesn't exist). | 76 // doesn't exist). |
69 type memStore gkvlite.Store | 77 type memStore interface { |
78 » datastore.TestingSnapshot | |
70 | 79 |
71 func (*memStore) ImATestingSnapshot() {} | 80 » GetCollection(name string) memCollection |
dnj
2016/04/22 06:09:45
nit: these *could* all be lowercase methods, since
iannucci
2016/04/22 06:56:25
I'd rather stick with uppercase, since it means th
| |
81 » GetCollectionNames() []string | |
82 » GetOrCreateCollection(name string) memCollection | |
83 » Snapshot() memStore | |
72 | 84 |
73 func newMemStore() *memStore { | 85 » IsReadOnly() bool |
74 » ret, err := gkvlite.NewStore(nil) | |
75 » memoryCorruption(err) | |
76 » return (*memStore)(ret) | |
77 } | |
78 | |
79 func (ms *memStore) Snapshot() *memStore { | |
80 » ret := (*memStore)((*gkvlite.Store)(ms).Snapshot()) | |
81 » runtime.SetFinalizer((*gkvlite.Store)(ret), func(s *gkvlite.Store) { | |
82 » » go s.Close() | |
83 » }) | |
84 » return ret | |
85 } | |
86 | |
87 func (ms *memStore) MakePrivateCollection(cmp gkvlite.KeyCompare) *memCollection { | |
88 » return (*memCollection)((*gkvlite.Store)(ms).MakePrivateCollection(cmp)) | |
89 } | |
90 | |
91 func (ms *memStore) GetCollection(name string) *memCollection { | |
92 » return (*memCollection)((*gkvlite.Store)(ms).GetCollection(name)) | |
93 } | |
94 | |
95 func (ms *memStore) SetCollection(name string, cmp gkvlite.KeyCompare) *memColle ction { | |
96 » return (*memCollection)((*gkvlite.Store)(ms).SetCollection(name, cmp)) | |
97 } | |
98 | |
99 func (ms *memStore) GetCollectionNames() []string { | |
100 » return (*gkvlite.Store)(ms).GetCollectionNames() | |
101 } | 86 } |
102 | 87 |
103 // memCollection is a gkvlite.Collection which will panic for anything which | 88 // memCollection is a gkvlite.Collection which will panic for anything which |
104 // might otherwise return an error. | 89 // might otherwise return an error. |
105 // | 90 // |
106 // This is reasonable for in-memory Store objects, since the only errors that | 91 // This is reasonable for in-memory Store objects, since the only errors that |
107 // should occur happen with file IO on the underlying file (which of course | 92 // should occur happen with file IO on the underlying file (which of course |
108 // doesn't exist. | 93 // doesn't exist. |
109 type memCollection gkvlite.Collection | 94 type memCollection interface { |
95 » Name() string | |
dnj
2016/04/22 06:09:45
(same r.e. export)
| |
96 » Delete(k []byte) bool | |
97 » Get(k []byte) []byte | |
98 » GetTotals() (numItems, numBytes uint64) | |
99 » MinItem(withValue bool) *gkvlite.Item | |
100 » Set(k, v []byte) | |
101 » VisitItemsAscend(target []byte, withValue bool, visitor gkvlite.ItemVisi tor) | |
110 | 102 |
111 func (mc *memCollection) Get(k []byte) []byte { | 103 » IsReadOnly() bool |
112 » ret, err := (*gkvlite.Collection)(mc).Get(k) | 104 } |
105 | |
106 type memStoreImpl struct { | |
107 » s *gkvlite.Store | |
108 » ro bool | |
109 } | |
110 | |
111 var _ memStore = (*memStoreImpl)(nil) | |
112 | |
113 func (*memStoreImpl) ImATestingSnapshot() {} | |
114 | |
115 func (ms *memStoreImpl) IsReadOnly() bool { return ms.ro } | |
116 | |
117 func newMemStore() memStore { | |
118 » store, err := gkvlite.NewStore(nil) | |
119 » memoryCorruption(err) | |
120 » ret := memStore(&memStoreImpl{store, false}) | |
121 » if *logMemCollectionFolder != "" { | |
122 » » ret = wrapTracingMemStore(ret) | |
123 » } | |
124 » return ret | |
125 } | |
126 | |
127 func (ms *memStoreImpl) Snapshot() memStore { | |
128 » if ms.ro { | |
129 » » return ms | |
130 » } | |
131 » ret := ms.s.Snapshot() | |
132 » runtime.SetFinalizer(ret, func(s *gkvlite.Store) { go s.Close() }) | |
dnj
2016/04/22 06:09:45
If we're doing this, should we just have store/col
iannucci
2016/04/22 06:56:25
I'm not aware of any benefit to doing this. Additi
| |
133 » return &memStoreImpl{ret, true} | |
134 } | |
135 | |
136 func (ms *memStoreImpl) GetCollection(name string) memCollection { | |
137 » coll := ms.s.GetCollection(name) | |
138 » if coll == nil { | |
139 » » return nil | |
140 » } | |
141 » return &memCollectionImpl{coll, ms.ro} | |
142 } | |
143 | |
144 func (ms *memStoreImpl) GetOrCreateCollection(name string) memCollection { | |
145 » coll := ms.GetCollection(name) | |
146 » if coll == nil { | |
147 » » coll = &memCollectionImpl{(ms.s.SetCollection(name, nil)), ms.ro } | |
148 » } | |
149 » return coll | |
150 } | |
151 | |
152 func (ms *memStoreImpl) GetCollectionNames() []string { | |
153 » return ms.s.GetCollectionNames() | |
154 } | |
155 | |
156 type memCollectionImpl struct { | |
157 » c *gkvlite.Collection | |
158 » ro bool | |
159 } | |
160 | |
161 var _ memCollection = (*memCollectionImpl)(nil) | |
162 | |
163 func (mc *memCollectionImpl) Name() string { return mc.c.Name() } | |
164 func (mc *memCollectionImpl) IsReadOnly() bool { return mc.ro } | |
165 | |
166 func (mc *memCollectionImpl) Get(k []byte) []byte { | |
167 » ret, err := mc.c.Get(k) | |
113 memoryCorruption(err) | 168 memoryCorruption(err) |
114 return ret | 169 return ret |
115 } | 170 } |
116 | 171 |
117 func (mc *memCollection) MinItem(withValue bool) *gkvlite.Item { | 172 func (mc *memCollectionImpl) MinItem(withValue bool) *gkvlite.Item { |
118 » ret, err := (*gkvlite.Collection)(mc).MinItem(withValue) | 173 » ret, err := mc.c.MinItem(withValue) |
119 memoryCorruption(err) | 174 memoryCorruption(err) |
120 return ret | 175 return ret |
121 } | 176 } |
122 | 177 |
123 func (mc *memCollection) Set(k, v []byte) { | 178 func (mc *memCollectionImpl) Set(k, v []byte) { |
124 » err := (*gkvlite.Collection)(mc).Set(k, v) | 179 » err := mc.c.Set(k, v) |
125 memoryCorruption(err) | 180 memoryCorruption(err) |
126 } | 181 } |
127 | 182 |
128 func (mc *memCollection) Delete(k []byte) bool { | 183 func (mc *memCollectionImpl) Delete(k []byte) bool { |
129 » ret, err := (*gkvlite.Collection)(mc).Delete(k) | 184 » ret, err := mc.c.Delete(k) |
130 memoryCorruption(err) | 185 memoryCorruption(err) |
131 return ret | 186 return ret |
132 } | 187 } |
133 | 188 |
134 func (mc *memCollection) VisitItemsAscend(target []byte, withValue bool, visitor gkvlite.ItemVisitor) { | 189 func (mc *memCollectionImpl) VisitItemsAscend(target []byte, withValue bool, vis itor gkvlite.ItemVisitor) { |
135 » err := (*gkvlite.Collection)(mc).VisitItemsAscend(target, withValue, vis itor) | 190 » if !mc.ro { |
191 » » panic("attempting to VisitItemsAscend from r/w memCollection") | |
dnj
2016/04/22 06:09:45
nit: above you use "rw", might as well be consiste
iannucci
2016/04/22 06:56:25
Done.
| |
192 » } | |
193 » err := mc.c.VisitItemsAscend(target, withValue, visitor) | |
136 memoryCorruption(err) | 194 memoryCorruption(err) |
137 } | 195 } |
138 | 196 |
139 func (mc *memCollection) GetTotals() (numItems, numBytes uint64) { | 197 func (mc *memCollectionImpl) GetTotals() (numItems, numBytes uint64) { |
140 » numItems, numBytes, err := (*gkvlite.Collection)(mc).GetTotals() | 198 » numItems, numBytes, err := mc.c.GetTotals() |
141 memoryCorruption(err) | 199 memoryCorruption(err) |
142 return | 200 return |
143 } | 201 } |
OLD | NEW |