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

Side by Side Diff: service/datastore/pls_impl.go

Issue 2342063003: Differentiate between single- and multi- props. (Closed)
Patch Set: Slice is now always a clone. This is marginally worse performance, but a much safer UI. Created 4 years, 3 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 | « service/datastore/multiarg.go ('k') | service/datastore/pls_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 LUCI Authors. All rights reserved. 1 // Copyright 2015 The LUCI Authors. All rights reserved.
2 // Use of this source code is governed under the Apache License, Version 2.0 2 // Use of this source code is governed under the Apache License, Version 2.0
3 // that can be found in the LICENSE file. 3 // that can be found in the LICENSE file.
4 4
5 // HEAVILY adapted from github.com/golang/appengine/datastore 5 // HEAVILY adapted from github.com/golang/appengine/datastore
6 6
7 package datastore 7 package datastore
8 8
9 import ( 9 import (
10 "fmt" 10 "fmt"
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after
62 useExtra := false 62 useExtra := false
63 extra := (*PropertyMap)(nil) 63 extra := (*PropertyMap)(nil)
64 if i, ok := p.c.bySpecial["extra"]; ok { 64 if i, ok := p.c.bySpecial["extra"]; ok {
65 useExtra = true 65 useExtra = true
66 f := p.c.byIndex[i] 66 f := p.c.byIndex[i]
67 if f.canSet { 67 if f.canSet {
68 extra = p.o.Field(i).Addr().Interface().(*PropertyMap) 68 extra = p.o.Field(i).Addr().Interface().(*PropertyMap)
69 } 69 }
70 } 70 }
71 t := reflect.Type(nil) 71 t := reflect.Type(nil)
72 » for name, props := range propMap { 72 » for name, pdata := range propMap {
73 » » multiple := len(props) > 1 73 » » pslice := pdata.Slice()
74 » » for i, prop := range props { 74 » » requireSlice := len(pslice) > 1
75 » » » if reason := loadInner(p.c, p.o, i, name, prop, multiple ); reason != "" { 75 » » for i, prop := range pslice {
76 » » » if reason := loadInner(p.c, p.o, i, name, prop, requireS lice); reason != "" {
76 if useExtra { 77 if useExtra {
77 if extra != nil { 78 if extra != nil {
78 if *extra == nil { 79 if *extra == nil {
79 *extra = make(PropertyMa p, 1) 80 *extra = make(PropertyMa p, 1)
80 } 81 }
81 » » » » » » (*extra)[name] = props 82 » » » » » » (*extra)[name] = pslice
82 } 83 }
83 break // go to the next property in prop Map 84 break // go to the next property in prop Map
84 } else { 85 } else {
85 if t == nil { 86 if t == nil {
86 t = p.o.Type() 87 t = p.o.Type()
87 } 88 }
88 convFailures = append(convFailures, &Err FieldMismatch{ 89 convFailures = append(convFailures, &Err FieldMismatch{
89 StructType: t, 90 StructType: t,
90 FieldName: name, 91 FieldName: name,
91 Reason: reason, 92 Reason: reason,
(...skipping 142 matching lines...) Expand 10 before | Expand all | Expand 10 after
234 ret := PropertyMap(nil) 235 ret := PropertyMap(nil)
235 if withMeta { 236 if withMeta {
236 if p.mgs != nil { 237 if p.mgs != nil {
237 ret = p.mgs.GetAllMeta() 238 ret = p.mgs.GetAllMeta()
238 } else { 239 } else {
239 ret = p.GetAllMeta() 240 ret = p.GetAllMeta()
240 } 241 }
241 } else { 242 } else {
242 ret = make(PropertyMap, len(p.c.byName)) 243 ret = make(PropertyMap, len(p.c.byName))
243 } 244 }
244 » if _, err := p.save(ret, "", ShouldIndex); err != nil { 245 » if _, err := p.save(ret, "", nil, ShouldIndex); err != nil {
245 return nil, err 246 return nil, err
246 } 247 }
247 return ret, nil 248 return ret, nil
248 } 249 }
249 250
250 func (p *structPLS) getDefaultKind() string { 251 func (p *structPLS) getDefaultKind() string {
251 if !p.o.IsValid() { 252 if !p.o.IsValid() {
252 return "" 253 return ""
253 } 254 }
254 return p.o.Type().Name() 255 return p.o.Type().Name()
255 } 256 }
256 257
257 func (p *structPLS) save(propMap PropertyMap, prefix string, is IndexSetting) (i dxCount int, err error) { 258 func (p *structPLS) save(propMap PropertyMap, prefix string, parentST *structTag , is IndexSetting) (idxCount int, err error) {
258 saveProp := func(name string, si IndexSetting, v reflect.Value, st *stru ctTag) (err error) { 259 saveProp := func(name string, si IndexSetting, v reflect.Value, st *stru ctTag) (err error) {
259 if st.substructCodec != nil { 260 if st.substructCodec != nil {
260 » » » count, err := (&structPLS{v, st.substructCodec, nil}).sa ve(propMap, name, si) 261 » » » count, err := (&structPLS{v, st.substructCodec, nil}).sa ve(propMap, name, st, si)
261 if err == nil { 262 if err == nil {
262 idxCount += count 263 idxCount += count
263 if idxCount > maxIndexedProperties { 264 if idxCount > maxIndexedProperties {
264 err = errors.New("gae: too many indexed properties") 265 err = errors.New("gae: too many indexed properties")
265 } 266 }
266 } 267 }
267 return err 268 return err
268 } 269 }
269 270
270 prop := Property{} 271 prop := Property{}
271 if st.convert { 272 if st.convert {
272 prop, err = v.Addr().Interface().(PropertyConverter).ToP roperty() 273 prop, err = v.Addr().Interface().(PropertyConverter).ToP roperty()
273 } else { 274 } else {
274 err = prop.SetValue(v.Interface(), si) 275 err = prop.SetValue(v.Interface(), si)
275 } 276 }
276 if err != nil { 277 if err != nil {
277 return err 278 return err
278 } 279 }
279 » » propMap[name] = append(propMap[name], prop) 280
281 » » // If we're a slice, or we are members in a slice, then use a Pr opertySlice.
282 » » if st.isSlice || (parentST != nil && parentST.isSlice) {
283 » » » var pslice PropertySlice
284 » » » if pdata := propMap[name]; pdata != nil {
285 » » » » pslice = pdata.(PropertySlice)
286 » » » }
287 » » » propMap[name] = append(pslice, prop)
288 » » } else {
289 » » » if _, ok := propMap[name]; ok {
290 » » » » return errors.New("non-slice property adding mul tiple PropertyMap entries")
291 » » » }
292 » » » propMap[name] = prop
293 » » }
294
280 if prop.IndexSetting() == ShouldIndex { 295 if prop.IndexSetting() == ShouldIndex {
281 idxCount++ 296 idxCount++
282 if idxCount > maxIndexedProperties { 297 if idxCount > maxIndexedProperties {
283 return errors.New("gae: too many indexed propert ies") 298 return errors.New("gae: too many indexed propert ies")
284 } 299 }
285 } 300 }
286 return nil 301 return nil
287 } 302 }
288 303
289 for i, st := range p.c.byIndex { 304 for i, st := range p.c.byIndex {
290 if st.name == "-" || st.isExtra { 305 if st.name == "-" || st.isExtra {
291 continue 306 continue
292 } 307 }
293 name := st.name 308 name := st.name
294 if prefix != "" { 309 if prefix != "" {
295 name = prefix + name 310 name = prefix + name
296 } 311 }
297 v := p.o.Field(i) 312 v := p.o.Field(i)
298 is1 := is 313 is1 := is
299 if st.idxSetting == NoIndex { 314 if st.idxSetting == NoIndex {
300 is1 = NoIndex 315 is1 = NoIndex
301 } 316 }
302 if st.isSlice { 317 if st.isSlice {
303 for j := 0; j < v.Len(); j++ { 318 for j := 0; j < v.Len(); j++ {
304 if err = saveProp(name, is1, v.Index(j), &st); e rr != nil { 319 if err = saveProp(name, is1, v.Index(j), &st); e rr != nil {
320 err = fmt.Errorf("gae: failed to save sl ice field %q: %v", name, err)
305 return 321 return
306 } 322 }
307 } 323 }
308 } else { 324 } else {
309 if err = saveProp(name, is1, v, &st); err != nil { 325 if err = saveProp(name, is1, v, &st); err != nil {
326 err = fmt.Errorf("gae: failed to save single fie ld %q: %v", name, err)
310 return 327 return
311 } 328 }
312 } 329 }
313 } 330 }
314 331
315 if i, ok := p.c.bySpecial["extra"]; ok { 332 if i, ok := p.c.bySpecial["extra"]; ok {
316 if p.c.byIndex[i].name != "-" { 333 if p.c.byIndex[i].name != "-" {
317 for fullName, vals := range p.o.Field(i).Interface().(Pr opertyMap) { 334 for fullName, vals := range p.o.Field(i).Interface().(Pr opertyMap) {
318 if _, ok := propMap[fullName]; !ok { 335 if _, ok := propMap[fullName]; !ok {
319 propMap[fullName] = vals 336 propMap[fullName] = vals
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after
363 380
364 func (p *structPLS) GetAllMeta() PropertyMap { 381 func (p *structPLS) GetAllMeta() PropertyMap {
365 needKind := true 382 needKind := true
366 ret := make(PropertyMap, len(p.c.byMeta)+1) 383 ret := make(PropertyMap, len(p.c.byMeta)+1)
367 for k, idx := range p.c.byMeta { 384 for k, idx := range p.c.byMeta {
368 if val, ok := p.getMetaFor(idx); ok { 385 if val, ok := p.getMetaFor(idx); ok {
369 p := Property{} 386 p := Property{}
370 if err := p.SetValue(val, NoIndex); err != nil { 387 if err := p.SetValue(val, NoIndex); err != nil {
371 continue 388 continue
372 } 389 }
373 » » » ret["$"+k] = []Property{p} 390 » » » ret["$"+k] = p
374 } 391 }
375 } 392 }
376 if needKind { 393 if needKind {
377 if _, ok := p.c.byMeta["kind"]; !ok { 394 if _, ok := p.c.byMeta["kind"]; !ok {
378 » » » ret["$kind"] = []Property{MkPropertyNI(p.getDefaultKind( ))} 395 » » » ret["$kind"] = MkPropertyNI(p.getDefaultKind())
379 } 396 }
380 } 397 }
381 return ret 398 return ret
382 } 399 }
383 400
384 func (p *structPLS) SetMeta(key string, val interface{}) bool { 401 func (p *structPLS) SetMeta(key string, val interface{}) bool {
385 idx, ok := p.c.byMeta[key] 402 idx, ok := p.c.byMeta[key]
386 if !ok { 403 if !ok {
387 return false 404 return false
388 } 405 }
(...skipping 288 matching lines...) Expand 10 before | Expand all | Expand 10 after
677 switch val { 694 switch val {
678 case "on", "On", "true": 695 case "on", "On", "true":
679 return true, nil 696 return true, nil
680 case "off", "Off", "false": 697 case "off", "Off", "false":
681 return false, nil 698 return false, nil
682 } 699 }
683 return nil, fmt.Errorf("Toggle field has bad/missing default, go t %q", val) 700 return nil, fmt.Errorf("Toggle field has bad/missing default, go t %q", val)
684 } 701 }
685 return nil, fmt.Errorf("helper: meta field with bad type/value %s/%q", t , val) 702 return nil, fmt.Errorf("helper: meta field with bad type/value %s/%q", t , val)
686 } 703 }
OLDNEW
« no previous file with comments | « service/datastore/multiarg.go ('k') | service/datastore/pls_test.go » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698