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

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

Issue 1365743002: Refactor serialization helpers from impl/memory -> service/datastore/serialize (Closed) Base URL: https://github.com/luci/gae.git@estimate_size
Patch Set: fix comments Created 5 years, 2 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
« no previous file with comments | « impl/memory/binary_tools.go ('k') | impl/memory/datastore_index_selection.go » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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 "fmt" 9 "fmt"
10 "sort" 10 "sort"
11 11
12 ds "github.com/luci/gae/service/datastore" 12 ds "github.com/luci/gae/service/datastore"
13 "github.com/luci/gae/service/datastore/serialize" 13 "github.com/luci/gae/service/datastore/serialize"
14 "github.com/luci/gkvlite" 14 "github.com/luci/gkvlite"
15 "github.com/luci/luci-go/common/stringset"
16 ) 15 )
17 16
18 type qIndexSlice []*ds.IndexDefinition 17 type qIndexSlice []*ds.IndexDefinition
19 18
20 func (s qIndexSlice) Len() int { return len(s) } 19 func (s qIndexSlice) Len() int { return len(s) }
21 func (s qIndexSlice) Swap(i, j int) { s[i], s[j] = s[j], s[i] } 20 func (s qIndexSlice) Swap(i, j int) { s[i], s[j] = s[j], s[i] }
22 func (s qIndexSlice) Less(i, j int) bool { return s[i].Less(s[j]) } 21 func (s qIndexSlice) Less(i, j int) bool { return s[i].Less(s[j]) }
23 22
24 func defaultIndexes(kind string, pmap ds.PropertyMap) []*ds.IndexDefinition { 23 func defaultIndexes(kind string, pmap ds.PropertyMap) []*ds.IndexDefinition {
25 ret := make(qIndexSlice, 0, 2*len(pmap)+1) 24 ret := make(qIndexSlice, 0, 2*len(pmap)+1)
(...skipping 12 matching lines...) Expand all
38 ret = append(ret, &ds.IndexDefinition{Kind: kind, SortBy: []ds.I ndexColumn{{Property: name}}}) 37 ret = append(ret, &ds.IndexDefinition{Kind: kind, SortBy: []ds.I ndexColumn{{Property: name}}})
39 ret = append(ret, &ds.IndexDefinition{Kind: kind, SortBy: []ds.I ndexColumn{{Property: name, Descending: true}}}) 38 ret = append(ret, &ds.IndexDefinition{Kind: kind, SortBy: []ds.I ndexColumn{{Property: name, Descending: true}}})
40 } 39 }
41 if serializationDeterministic { 40 if serializationDeterministic {
42 sort.Sort(ret) 41 sort.Sort(ret)
43 } 42 }
44 return ret 43 return ret
45 } 44 }
46 45
47 func indexEntriesWithBuiltins(k *ds.Key, pm ds.PropertyMap, complexIdxs []*ds.In dexDefinition) *memStore { 46 func indexEntriesWithBuiltins(k *ds.Key, pm ds.PropertyMap, complexIdxs []*ds.In dexDefinition) *memStore {
48 » sip := partiallySerialize(k, pm) 47 » sip := serialize.PropertyMapPartially(k, pm)
49 » return sip.indexEntries(k.Namespace(), append(defaultIndexes(k.Kind(), p m), complexIdxs...)) 48 » return indexEntries(sip, k.Namespace(), append(defaultIndexes(k.Kind(), pm), complexIdxs...))
50 }
51
52 // serializedPvals is all of the serialized DSProperty values in qASC order.
53 type serializedPvals [][]byte
54
55 func (s serializedPvals) Len() int { return len(s) }
56 func (s serializedPvals) Swap(i, j int) { s[i], s[j] = s[j], s[i] }
57 func (s serializedPvals) Less(i, j int) bool { return bytes.Compare(s[i], s[j]) < 0 }
58
59 // prop name -> [<serialized DSProperty>, ...]
60 // includes special values '__key__' and '__ancestor__' which contains all of
61 // the ancestor entries for this key.
62 type serializedIndexablePmap map[string]serializedPvals
63
64 func serializeRow(vals []ds.Property) serializedPvals {
65 » dups := stringset.New(0)
66 » ret := make(serializedPvals, 0, len(vals))
67 » for _, v := range vals {
68 » » if v.IndexSetting() == ds.NoIndex {
69 » » » continue
70 » » }
71 » » data := serialize.ToBytes(v.ForIndex())
72 » » dataS := string(data)
73 » » if !dups.Add(dataS) {
74 » » » continue
75 » » }
76 » » ret = append(ret, data)
77 » }
78 » return ret
79 }
80
81 func partiallySerialize(k *ds.Key, pm ds.PropertyMap) (ret serializedIndexablePm ap) {
82 » ret = make(serializedIndexablePmap, len(pm)+2)
83 » if k == nil {
84 » » impossible(fmt.Errorf("key to partiallySerialize is nil"))
85 » }
86 » ret["__key__"] = [][]byte{serialize.ToBytes(ds.MkProperty(k))}
87 » for k != nil {
88 » » ret["__ancestor__"] = append(ret["__ancestor__"], serialize.ToBy tes(ds.MkProperty(k)))
89 » » k = k.Parent()
90 » }
91 » for k, vals := range pm {
92 » » newVals := serializeRow(vals)
93 » » if len(newVals) > 0 {
94 » » » ret[k] = newVals
95 » » }
96 » }
97 » return
98 } 49 }
99 50
100 // indexRowGen contains enough information to generate all of the index rows whi ch 51 // indexRowGen contains enough information to generate all of the index rows whi ch
101 // correspond with a propertyList and a ds.IndexDefinition. 52 // correspond with a propertyList and a ds.IndexDefinition.
102 type indexRowGen struct { 53 type indexRowGen struct {
103 » propVec []serializedPvals 54 » propVec []serialize.SerializedPslice
104 decending []bool 55 decending []bool
105 } 56 }
106 57
107 // permute calls cb for each index row, in the sorted order of the rows. 58 // permute calls cb for each index row, in the sorted order of the rows.
108 func (s indexRowGen) permute(collSetFn func(k, v []byte)) { 59 func (s indexRowGen) permute(collSetFn func(k, v []byte)) {
109 iVec := make([]int, len(s.propVec)) 60 iVec := make([]int, len(s.propVec))
110 iVecLim := make([]int, len(s.propVec)) 61 iVecLim := make([]int, len(s.propVec))
111 62
112 incPos := func() bool { 63 incPos := func() bool {
113 for i := len(iVec) - 1; i >= 0; i-- { 64 for i := len(iVec) - 1; i >= 0; i-- {
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after
160 } 111 }
161 } 112 }
162 113
163 type matcher struct { 114 type matcher struct {
164 buf indexRowGen 115 buf indexRowGen
165 } 116 }
166 117
167 // matcher.match checks to see if the mapped, serialized property values 118 // matcher.match checks to see if the mapped, serialized property values
168 // match the index. If they do, it returns a indexRowGen. Do not write or modify 119 // match the index. If they do, it returns a indexRowGen. Do not write or modify
169 // the data in the indexRowGen. 120 // the data in the indexRowGen.
170 func (m *matcher) match(sortBy []ds.IndexColumn, sip serializedIndexablePmap) (i ndexRowGen, bool) { 121 func (m *matcher) match(sortBy []ds.IndexColumn, sip serialize.SerializedPmap) ( indexRowGen, bool) {
171 m.buf.propVec = m.buf.propVec[:0] 122 m.buf.propVec = m.buf.propVec[:0]
172 m.buf.decending = m.buf.decending[:0] 123 m.buf.decending = m.buf.decending[:0]
173 for _, sb := range sortBy { 124 for _, sb := range sortBy {
174 if pv, ok := sip[sb.Property]; ok { 125 if pv, ok := sip[sb.Property]; ok {
175 m.buf.propVec = append(m.buf.propVec, pv) 126 m.buf.propVec = append(m.buf.propVec, pv)
176 m.buf.decending = append(m.buf.decending, sb.Descending) 127 m.buf.decending = append(m.buf.decending, sb.Descending)
177 } else { 128 } else {
178 return indexRowGen{}, false 129 return indexRowGen{}, false
179 } 130 }
180 } 131 }
181 return m.buf, true 132 return m.buf, true
182 } 133 }
183 134
184 func (sip serializedIndexablePmap) indexEntries(ns string, idxs []*ds.IndexDefin ition) *memStore { 135 func indexEntries(sip serialize.SerializedPmap, ns string, idxs []*ds.IndexDefin ition) *memStore {
185 ret := newMemStore() 136 ret := newMemStore()
186 idxColl := ret.SetCollection("idx", nil) 137 idxColl := ret.SetCollection("idx", nil)
187 138
188 mtch := matcher{} 139 mtch := matcher{}
189 for _, idx := range idxs { 140 for _, idx := range idxs {
190 idx = idx.Normalize() 141 idx = idx.Normalize()
191 if irg, ok := mtch.match(idx.GetFullSortOrder(), sip); ok { 142 if irg, ok := mtch.match(idx.GetFullSortOrder(), sip); ok {
192 idxBin := serialize.ToBytes(*idx.PrepForIdxTable()) 143 idxBin := serialize.ToBytes(*idx.PrepForIdxTable())
193 idxColl.Set(idxBin, []byte{}) 144 idxColl.Set(idxBin, []byte{})
194 coll := ret.SetCollection(fmt.Sprintf("idx:%s:%s", ns, i dxBin), nil) 145 coll := ret.SetCollection(fmt.Sprintf("idx:%s:%s", ns, i dxBin), nil)
(...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after
284 if allEnts := store.GetCollection("ents:" + ns); allEnts != nil { 235 if allEnts := store.GetCollection("ents:" + ns); allEnts != nil {
285 allEnts.VisitItemsAscend(nil, true, func(i *gkvlite.Item) bool { 236 allEnts.VisitItemsAscend(nil, true, func(i *gkvlite.Item) bool {
286 pm, err := rpmWoCtx(i.Val, ns) 237 pm, err := rpmWoCtx(i.Val, ns)
287 memoryCorruption(err) 238 memoryCorruption(err)
288 239
289 prop, err := serialize.ReadProperty(bytes.NewBuffer(i.Ke y), serialize.WithoutContext, globalAppID, ns) 240 prop, err := serialize.ReadProperty(bytes.NewBuffer(i.Ke y), serialize.WithoutContext, globalAppID, ns)
290 memoryCorruption(err) 241 memoryCorruption(err)
291 242
292 k := prop.Value().(*ds.Key) 243 k := prop.Value().(*ds.Key)
293 244
294 » » » sip := partiallySerialize(k, pm) 245 » » » sip := serialize.PropertyMapPartially(k, pm)
295 246
296 mergeIndexes(ns, store, 247 mergeIndexes(ns, store,
297 newMemStore(), 248 newMemStore(),
298 » » » » sip.indexEntries(ns, normalized)) 249 » » » » indexEntries(sip, ns, normalized))
299 return true 250 return true
300 }) 251 })
301 } 252 }
302 } 253 }
303 254
304 func updateIndexes(store *memStore, key *ds.Key, oldEnt, newEnt ds.PropertyMap) { 255 func updateIndexes(store *memStore, key *ds.Key, oldEnt, newEnt ds.PropertyMap) {
305 // load all current complex query index definitions. 256 // load all current complex query index definitions.
306 compIdx := []*ds.IndexDefinition{} 257 compIdx := []*ds.IndexDefinition{}
307 walkCompIdxs(store, nil, func(i *ds.IndexDefinition) bool { 258 walkCompIdxs(store, nil, func(i *ds.IndexDefinition) bool {
308 compIdx = append(compIdx, i) 259 compIdx = append(compIdx, i)
309 return true 260 return true
310 }) 261 })
311 262
312 mergeIndexes(key.Namespace(), store, 263 mergeIndexes(key.Namespace(), store,
313 indexEntriesWithBuiltins(key, oldEnt, compIdx), 264 indexEntriesWithBuiltins(key, oldEnt, compIdx),
314 indexEntriesWithBuiltins(key, newEnt, compIdx)) 265 indexEntriesWithBuiltins(key, newEnt, compIdx))
315 } 266 }
OLDNEW
« no previous file with comments | « impl/memory/binary_tools.go ('k') | impl/memory/datastore_index_selection.go » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698