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

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

Issue 1911263002: Fix memory corruption bug in impl/memory (Closed) Base URL: https://chromium.googlesource.com/external/github.com/luci/gae@master
Patch Set: Created 4 years, 8 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
OLDNEW
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
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 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698