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("old collection is r/w") |
| 19 » } |
| 20 » if n != nil && !n.IsReadOnly() { |
| 21 » » panic("new collection is r/w") |
| 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 |
| 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 |
| 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() }) |
| 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") |
| 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 |