Chromium Code Reviews| 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 |