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

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

Issue 1427933002: Decouple PLS from MGS. (Closed) Base URL: https://github.com/luci/gae@master
Patch Set: Add test for basic struct extraction. Created 5 years, 1 month 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/pls.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 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 // 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 17 matching lines...) Expand all
28 convert bool 28 convert bool
29 metaVal interface{} 29 metaVal interface{}
30 canSet bool 30 canSet bool
31 } 31 }
32 32
33 type structCodec struct { 33 type structCodec struct {
34 byMeta map[string]int 34 byMeta map[string]int
35 byName map[string]int 35 byName map[string]int
36 byIndex []structTag 36 byIndex []structTag
37 hasSlice bool 37 hasSlice bool
38 mgs bool
39 problem error 38 problem error
40 } 39 }
41 40
42 type structPLS struct { 41 type structPLS struct {
43 o reflect.Value 42 o reflect.Value
44 c *structCodec 43 c *structCodec
45 } 44 }
46 45
47 func (p *structPLS) getMGS() MetaGetterSetter {
48 if !p.c.mgs {
49 return nil
50 }
51 return p.o.Addr().Interface().(MetaGetterSetter)
52 }
53
54 var _ PropertyLoadSaver = (*structPLS)(nil) 46 var _ PropertyLoadSaver = (*structPLS)(nil)
55 47
56 // typeMismatchReason returns a string explaining why the property p could not 48 // typeMismatchReason returns a string explaining why the property p could not
57 // be stored in an entity field of type v.Type(). 49 // be stored in an entity field of type v.Type().
58 func typeMismatchReason(val interface{}, v reflect.Value) string { 50 func typeMismatchReason(val interface{}, v reflect.Value) string {
59 entityType := reflect.TypeOf(val) 51 entityType := reflect.TypeOf(val)
60 return fmt.Sprintf("type mismatch: %s versus %v", entityType, v.Type()) 52 return fmt.Sprintf("type mismatch: %s versus %v", entityType, v.Type())
61 } 53 }
62 54
63 func (p *structPLS) Load(propMap PropertyMap) error { 55 func (p *structPLS) Load(propMap PropertyMap) error {
(...skipping 155 matching lines...) Expand 10 before | Expand all | Expand 10 after
219 } else { 211 } else {
220 ret = make(PropertyMap, len(p.c.byName)) 212 ret = make(PropertyMap, len(p.c.byName))
221 } 213 }
222 if _, err := p.save(ret, "", ShouldIndex); err != nil { 214 if _, err := p.save(ret, "", ShouldIndex); err != nil {
223 return nil, err 215 return nil, err
224 } 216 }
225 return ret, nil 217 return ret, nil
226 } 218 }
227 219
228 func (p *structPLS) getDefaultKind() string { 220 func (p *structPLS) getDefaultKind() string {
221 if !p.o.IsValid() {
222 return ""
223 }
229 return p.o.Type().Name() 224 return p.o.Type().Name()
230 } 225 }
231 226
232 func (p *structPLS) save(propMap PropertyMap, prefix string, is IndexSetting) (i dxCount int, err error) { 227 func (p *structPLS) save(propMap PropertyMap, prefix string, is IndexSetting) (i dxCount int, err error) {
233 if err = p.Problem(); err != nil { 228 if err = p.Problem(); err != nil {
234 return 229 return
235 } 230 }
236 231
237 saveProp := func(name string, si IndexSetting, v reflect.Value, st *stru ctTag) (err error) { 232 saveProp := func(name string, si IndexSetting, v reflect.Value, st *stru ctTag) (err error) {
238 if st.substructCodec != nil { 233 if st.substructCodec != nil {
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after
295 290
296 func (p *structPLS) GetMeta(key string) (interface{}, error) { 291 func (p *structPLS) GetMeta(key string) (interface{}, error) {
297 if err := p.Problem(); err != nil { 292 if err := p.Problem(); err != nil {
298 return nil, err 293 return nil, err
299 } 294 }
300 295
301 if idx, ok := p.c.byMeta[key]; ok { 296 if idx, ok := p.c.byMeta[key]; ok {
302 return p.getMetaFor(idx), nil 297 return p.getMetaFor(idx), nil
303 } 298 }
304 299
305 if p.c.mgs {
306 ret, err := p.getMGS().GetMeta(key)
307 if err == nil {
308 return ret, err
309 } else if err != ErrMetaFieldUnset {
310 return nil, err
311 }
312 }
313 if key == "kind" { 300 if key == "kind" {
314 return p.getDefaultKind(), nil 301 return p.getDefaultKind(), nil
315 } 302 }
316 return nil, ErrMetaFieldUnset 303 return nil, ErrMetaFieldUnset
317 } 304 }
318 305
319 func (p *structPLS) getMetaFor(idx int) interface{} { 306 func (p *structPLS) getMetaFor(idx int) interface{} {
320 st := p.c.byIndex[idx] 307 st := p.c.byIndex[idx]
321 val := st.metaVal 308 val := st.metaVal
322 f := p.o.Field(idx) 309 f := p.o.Field(idx)
323 if st.canSet { 310 if st.canSet {
324 if !reflect.DeepEqual(reflect.Zero(f.Type()).Interface(), f.Inte rface()) { 311 if !reflect.DeepEqual(reflect.Zero(f.Type()).Interface(), f.Inte rface()) {
325 val = f.Interface() 312 val = f.Interface()
326 if bf, ok := val.(Toggle); ok { 313 if bf, ok := val.(Toggle); ok {
327 val = bf == On // true if On, otherwise false 314 val = bf == On // true if On, otherwise false
328 } 315 }
329 } 316 }
330 } 317 }
331 return val 318 return val
332 } 319 }
333 320
334 func (p *structPLS) GetAllMeta() PropertyMap { 321 func (p *structPLS) GetAllMeta() PropertyMap {
335 ret := PropertyMap(nil)
336 needKind := true 322 needKind := true
337 » if p.c.mgs { 323 » ret := make(PropertyMap, len(p.c.byMeta)+1)
338 » » ret = p.getMGS().GetAllMeta()
iannucci 2015/10/30 21:29:29 This is the code that I was wondering about. I'm n
dnj 2015/10/30 21:40:04 Gone b/c: 1) No fallthroughs, structPLS is pure no
339 » » _, haveKind := ret["$kind"]
340 » » needKind = !haveKind
341 » } else {
342 » » ret = make(PropertyMap, len(p.c.byMeta)+1)
343 » }
344 for k, idx := range p.c.byMeta { 324 for k, idx := range p.c.byMeta {
345 val := p.getMetaFor(idx) 325 val := p.getMetaFor(idx)
346 p := Property{} 326 p := Property{}
347 if err := p.SetValue(val, NoIndex); err != nil { 327 if err := p.SetValue(val, NoIndex); err != nil {
348 continue 328 continue
349 } 329 }
350 ret["$"+k] = []Property{p} 330 ret["$"+k] = []Property{p}
351 } 331 }
352 if needKind { 332 if needKind {
353 if _, ok := p.c.byMeta["kind"]; !ok { 333 if _, ok := p.c.byMeta["kind"]; !ok {
354 ret["$kind"] = []Property{MkPropertyNI(p.getDefaultKind( ))} 334 ret["$kind"] = []Property{MkPropertyNI(p.getDefaultKind( ))}
355 } 335 }
356 } 336 }
357 return ret 337 return ret
358 } 338 }
359 339
360 func (p *structPLS) GetMetaDefault(key string, def interface{}) interface{} { 340 func (p *structPLS) GetMetaDefault(key string, def interface{}) interface{} {
361 return GetMetaDefaultImpl(p.GetMeta, key, def) 341 return GetMetaDefaultImpl(p.GetMeta, key, def)
362 } 342 }
363 343
364 func (p *structPLS) SetMeta(key string, val interface{}) (err error) { 344 func (p *structPLS) SetMeta(key string, val interface{}) (err error) {
365 if err = p.Problem(); err != nil { 345 if err = p.Problem(); err != nil {
366 return 346 return
367 } 347 }
368 idx, ok := p.c.byMeta[key] 348 idx, ok := p.c.byMeta[key]
369 if !ok { 349 if !ok {
370 if p.c.mgs {
371 return p.getMGS().SetMeta(key, val)
372 }
373 return ErrMetaFieldUnset 350 return ErrMetaFieldUnset
374 } 351 }
375 if !p.c.byIndex[idx].canSet { 352 if !p.c.byIndex[idx].canSet {
376 return fmt.Errorf("gae/helper: cannot set meta %q: unexported fi eld", key) 353 return fmt.Errorf("gae/helper: cannot set meta %q: unexported fi eld", key)
377 } 354 }
378 // setting a BoolField 355 // setting a BoolField
379 if b, ok := val.(bool); ok { 356 if b, ok := val.(bool); ok {
380 if b { 357 if b {
381 val = On 358 val = On
382 } else { 359 } else {
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after
441 418
442 me := func(fmtStr string, args ...interface{}) error { 419 me := func(fmtStr string, args ...interface{}) error {
443 return fmt.Errorf(fmtStr, args...) 420 return fmt.Errorf(fmtStr, args...)
444 } 421 }
445 422
446 c = &structCodec{ 423 c = &structCodec{
447 byIndex: make([]structTag, t.NumField()), 424 byIndex: make([]structTag, t.NumField()),
448 byName: make(map[string]int, t.NumField()), 425 byName: make(map[string]int, t.NumField()),
449 byMeta: make(map[string]int, t.NumField()), 426 byMeta: make(map[string]int, t.NumField()),
450 problem: errRecursiveStruct, // we'll clear this later if it's n ot recursive 427 problem: errRecursiveStruct, // we'll clear this later if it's n ot recursive
451 mgs: reflect.PtrTo(t).Implements(typeOfMGS),
452 } 428 }
453 defer func() { 429 defer func() {
454 // If the codec has a problem, free up the indexes 430 // If the codec has a problem, free up the indexes
455 if c.problem != nil { 431 if c.problem != nil {
456 c.byIndex = nil 432 c.byIndex = nil
457 c.byName = nil 433 c.byName = nil
458 c.byMeta = nil 434 c.byMeta = nil
459 } 435 }
460 }() 436 }()
461 structCodecs[t] = c 437 structCodecs[t] = c
(...skipping 142 matching lines...) Expand 10 before | Expand all | Expand 10 after
604 switch val { 580 switch val {
605 case "on", "On", "true": 581 case "on", "On", "true":
606 return true, nil 582 return true, nil
607 case "off", "Off", "false": 583 case "off", "Off", "false":
608 return false, nil 584 return false, nil
609 } 585 }
610 return nil, fmt.Errorf("Toggle field has bad/missing default, go t %q", val) 586 return nil, fmt.Errorf("Toggle field has bad/missing default, go t %q", val)
611 } 587 }
612 return nil, fmt.Errorf("helper: meta field with bad type/value %s/%q", t , val) 588 return nil, fmt.Errorf("helper: meta field with bad type/value %s/%q", t , val)
613 } 589 }
OLDNEW
« no previous file with comments | « service/datastore/pls.go ('k') | service/datastore/pls_test.go » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698