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

Side by Side Diff: impl/memory/datastore_index_selection.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: fix comments 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
« no previous file with comments | « impl/memory/datastore_index.go ('k') | impl/memory/datastore_index_test.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"
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after
63 // metadata describing the total number of columns that this query requi res to 63 // metadata describing the total number of columns that this query requi res to
64 // execute perfectly. 64 // execute perfectly.
65 numCols int 65 numCols int
66 } 66 }
67 67
68 type indexDefinitionSortable struct { 68 type indexDefinitionSortable struct {
69 // eqFilts is the list of ACTUAL prefix columns. Note that it may contai n 69 // eqFilts is the list of ACTUAL prefix columns. Note that it may contai n
70 // redundant columns! (e.g. (tag, tag) is a perfectly valid prefix, becu ase 70 // redundant columns! (e.g. (tag, tag) is a perfectly valid prefix, becu ase
71 // (tag=1, tag=2) is a perfectly valid query). 71 // (tag=1, tag=2) is a perfectly valid query).
72 eqFilts []ds.IndexColumn 72 eqFilts []ds.IndexColumn
73 » coll *memCollection 73 » coll memCollection
74 } 74 }
75 75
76 func (i *indexDefinitionSortable) hasAncestor() bool { 76 func (i *indexDefinitionSortable) hasAncestor() bool {
77 return len(i.eqFilts) > 0 && i.eqFilts[0].Property == "__ancestor__" 77 return len(i.eqFilts) > 0 && i.eqFilts[0].Property == "__ancestor__"
78 } 78 }
79 79
80 func (i *indexDefinitionSortable) numEqHits(c *constraints) int { 80 func (i *indexDefinitionSortable) numEqHits(c *constraints) int {
81 ret := 0 81 ret := 0
82 for _, filt := range i.eqFilts { 82 for _, filt := range i.eqFilts {
83 if _, ok := c.constraints[filt.Property]; ok { 83 if _, ok := c.constraints[filt.Property]; ok {
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after
124 // maybeAddDefinition possibly adds a new indexDefinitionSortable to this slice. 124 // maybeAddDefinition possibly adds a new indexDefinitionSortable to this slice.
125 // It's only added if it could be useful in servicing q, otherwise this function 125 // It's only added if it could be useful in servicing q, otherwise this function
126 // is a noop. 126 // is a noop.
127 // 127 //
128 // This returns true iff the proposed index is OK and depletes missingTerms to 128 // This returns true iff the proposed index is OK and depletes missingTerms to
129 // empty. 129 // empty.
130 // 130 //
131 // If the proposed index is PERFECT (e.g. contains enough columns to cover all 131 // If the proposed index is PERFECT (e.g. contains enough columns to cover all
132 // equality filters, and also has the correct suffix), idxs will be replaced 132 // equality filters, and also has the correct suffix), idxs will be replaced
133 // with JUST that index, and this will return true. 133 // with JUST that index, and this will return true.
134 func (idxs *indexDefinitionSortableSlice) maybeAddDefinition(q *reducedQuery, s *memStore, missingTerms stringset.Set, id *ds.IndexDefinition) bool { 134 func (idxs *indexDefinitionSortableSlice) maybeAddDefinition(q *reducedQuery, s memStore, missingTerms stringset.Set, id *ds.IndexDefinition) bool {
135 // Kindless queries are handled elsewhere. 135 // Kindless queries are handled elsewhere.
136 if id.Kind != q.kind { 136 if id.Kind != q.kind {
137 impossible( 137 impossible(
138 fmt.Errorf("maybeAddDefinition given index with wrong ki nd %q v %q", id.Kind, q.kind)) 138 fmt.Errorf("maybeAddDefinition given index with wrong ki nd %q v %q", id.Kind, q.kind))
139 } 139 }
140 140
141 // If we're an ancestor query, and the index is compound, but doesn't in clude 141 // If we're an ancestor query, and the index is compound, but doesn't in clude
142 // an Ancestor field, it doesn't work. Builtin indexes can be used for 142 // an Ancestor field, it doesn't work. Builtin indexes can be used for
143 // ancestor queries (and have !Ancestor), assuming that it's only equali ty 143 // ancestor queries (and have !Ancestor), assuming that it's only equali ty
144 // filters (plus inequality on __key__), or a single inequality. 144 // filters (plus inequality on __key__), or a single inequality.
(...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after
223 *idxs = indexDefinitionSortableSlice{toAdd} 223 *idxs = indexDefinitionSortableSlice{toAdd}
224 } else { 224 } else {
225 *idxs = append(*idxs, toAdd) 225 *idxs = append(*idxs, toAdd)
226 } 226 }
227 return missingTerms.Len() == 0 227 return missingTerms.Len() == 0
228 } 228 }
229 229
230 // getRelevantIndexes retrieves the relevant indexes which could be used to 230 // getRelevantIndexes retrieves the relevant indexes which could be used to
231 // service q. It returns nil if it's not possible to service q with the current 231 // service q. It returns nil if it's not possible to service q with the current
232 // indexes. 232 // indexes.
233 func getRelevantIndexes(q *reducedQuery, s *memStore) (indexDefinitionSortableSl ice, error) { 233 func getRelevantIndexes(q *reducedQuery, s memStore) (indexDefinitionSortableSli ce, error) {
234 missingTerms := stringset.New(len(q.eqFilters)) 234 missingTerms := stringset.New(len(q.eqFilters))
235 for k := range q.eqFilters { 235 for k := range q.eqFilters {
236 if k == "__ancestor__" { 236 if k == "__ancestor__" {
237 // ancestor is not a prefix which can be satisfied by a single index. It 237 // ancestor is not a prefix which can be satisfied by a single index. It
238 // must be satisfied by ALL indexes (and has special log ic for this in 238 // must be satisfied by ALL indexes (and has special log ic for this in
239 // the addDefinition logic) 239 // the addDefinition logic)
240 continue 240 continue
241 } 241 }
242 missingTerms.Add(k) 242 missingTerms.Add(k)
243 } 243 }
(...skipping 217 matching lines...) Expand 10 before | Expand all | Expand 10 after
461 // in ret.original above will be sufficient. 461 // in ret.original above will be sufficient.
462 continue 462 continue
463 } 463 }
464 ret.constraints[prop] = bvals 464 ret.constraints[prop] = bvals
465 } 465 }
466 return ret 466 return ret
467 } 467 }
468 468
469 // getIndexes returns a set of iterator definitions. Iterating over these 469 // getIndexes returns a set of iterator definitions. Iterating over these
470 // will result in matching suffixes. 470 // will result in matching suffixes.
471 func getIndexes(q *reducedQuery, s *memStore) ([]*iterDefinition, error) { 471 func getIndexes(q *reducedQuery, s memStore) ([]*iterDefinition, error) {
472 relevantIdxs := indexDefinitionSortableSlice(nil) 472 relevantIdxs := indexDefinitionSortableSlice(nil)
473 if q.kind == "" { 473 if q.kind == "" {
474 if coll := s.GetCollection("ents:" + q.ns); coll != nil { 474 if coll := s.GetCollection("ents:" + q.ns); coll != nil {
475 relevantIdxs = indexDefinitionSortableSlice{{coll: coll} } 475 relevantIdxs = indexDefinitionSortableSlice{{coll: coll} }
476 } 476 }
477 } else { 477 } else {
478 err := error(nil) 478 err := error(nil)
479 relevantIdxs, err = getRelevantIndexes(q, s) 479 relevantIdxs, err = getRelevantIndexes(q, s)
480 if err != nil { 480 if err != nil {
481 return nil, err 481 return nil, err
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after
542 if bestIdx == nil { 542 if bestIdx == nil {
543 // something is really wrong here... if relevantIdxs is !nil, then we 543 // something is really wrong here... if relevantIdxs is !nil, then we
544 // should always be able to make progress in this loop. 544 // should always be able to make progress in this loop.
545 impossible(fmt.Errorf("deadlock: cannot fulfil query?")) 545 impossible(fmt.Errorf("deadlock: cannot fulfil query?"))
546 } 546 }
547 ret = append(ret, generate(q, bestIdx, constraints)) 547 ret = append(ret, generate(q, bestIdx, constraints))
548 } 548 }
549 549
550 return ret, nil 550 return ret, nil
551 } 551 }
OLDNEW
« no previous file with comments | « impl/memory/datastore_index.go ('k') | impl/memory/datastore_index_test.go » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698