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 datastore | 5 package datastore |
6 | 6 |
7 import ( | 7 import ( |
8 "fmt" | 8 "fmt" |
9 "reflect" | 9 "reflect" |
10 | 10 |
11 "github.com/luci/luci-go/common/errors" | 11 "github.com/luci/luci-go/common/errors" |
12 ) | 12 ) |
13 | 13 |
14 type datastoreImpl struct{ RawInterface } | 14 type datastoreImpl struct{ RawInterface } |
15 | 15 |
16 var _ Interface = (*datastoreImpl)(nil) | 16 var _ Interface = (*datastoreImpl)(nil) |
17 | 17 |
18 func (d *datastoreImpl) KeyForObj(src interface{}) Key { | 18 func (d *datastoreImpl) KeyForObj(src interface{}) Key { |
19 ret, err := d.KeyForObjErr(src) | 19 ret, err := d.KeyForObjErr(src) |
20 if err != nil { | 20 if err != nil { |
21 panic(err) | 21 panic(err) |
22 } | 22 } |
23 return ret | 23 return ret |
24 } | 24 } |
25 | 25 |
26 func (d *datastoreImpl) KeyForObjErr(src interface{}) (Key, error) { | 26 func (d *datastoreImpl) KeyForObjErr(src interface{}) (Key, error) { |
27 return newKeyObjErr(d.NewKey, src) | 27 return newKeyObjErr(d.NewKey, src) |
28 } | 28 } |
29 | 29 |
30 func (d *datastoreImpl) Run(q Query, proto interface{}, cb RunCB) error { | 30 func (d *datastoreImpl) Run(q Query, cbIface interface{}) error { |
31 » if _, ok := proto.(*Key); ok { | 31 » // TODO(riannucci): Profile and determine if any of this is causing a re
al |
32 » » return d.RawInterface.Run(q.KeysOnly(), func(k Key, _ PropertyMa
p, gc func() (Cursor, error)) bool { | 32 » // slowdown. Could potentially cache reflection stuff by cbType? |
| 33 » cbTyp := reflect.TypeOf(cbIface) |
| 34 |
| 35 » badSig := false |
| 36 » mat := multiArgType{} |
| 37 » isKey := false |
| 38 |
| 39 » if cbTyp.Kind() == reflect.Func && cbTyp.NumIn() == 2 && cbTyp.NumOut()
== 1 { |
| 40 » » firstArg := cbTyp.In(0) |
| 41 » » if firstArg == typeOfKey { |
| 42 » » » isKey = true |
| 43 » » } else { |
| 44 » » » mat = parseArg(firstArg) |
| 45 » » » badSig = !mat.valid || mat.newElem == nil |
| 46 » » } |
| 47 » } else { |
| 48 » » badSig = true |
| 49 » } |
| 50 |
| 51 » if badSig || cbTyp.Out(0) != typeOfBool || cbTyp.In(1) != typeOfCursorCB
{ |
| 52 » » panic(fmt.Errorf( |
| 53 » » » "cb does not match the required callback signature: `%T`
!= `func(TYPE, CursorCB) bool`", |
| 54 » » » cbIface)) |
| 55 » } |
| 56 |
| 57 » if isKey { |
| 58 » » cb := cbIface.(func(Key, CursorCB) bool) |
| 59 » » return d.RawInterface.Run(q.KeysOnly(), func(k Key, _ PropertyMa
p, gc CursorCB) bool { |
33 return cb(k, gc) | 60 return cb(k, gc) |
34 }) | 61 }) |
35 } | 62 } |
36 | 63 |
37 » mat := parseArg(reflect.TypeOf(proto)) | 64 » cbVal := reflect.ValueOf(cbIface) |
38 » if !mat.valid || mat.newElem == nil { | |
39 » » return fmt.Errorf("invalid Run proto type: %T", proto) | |
40 » } | |
41 | 65 |
42 innerErr := error(nil) | 66 innerErr := error(nil) |
43 » err := d.RawInterface.Run(q, func(k Key, pm PropertyMap, gc func() (Curs
or, error)) bool { | 67 » err := d.RawInterface.Run(q, func(k Key, pm PropertyMap, gc CursorCB) bo
ol { |
44 itm := mat.newElem() | 68 itm := mat.newElem() |
45 if innerErr = mat.setPM(itm, pm); innerErr != nil { | 69 if innerErr = mat.setPM(itm, pm); innerErr != nil { |
46 return false | 70 return false |
47 } | 71 } |
48 mat.setKey(itm, k) | 72 mat.setKey(itm, k) |
49 » » return cb(itm.Interface(), gc) | 73 » » return cbVal.Call([]reflect.Value{itm, reflect.ValueOf(gc)})[0].
Bool() |
50 }) | 74 }) |
51 if err == nil { | 75 if err == nil { |
52 err = innerErr | 76 err = innerErr |
53 } | 77 } |
54 return err | 78 return err |
55 } | 79 } |
56 | 80 |
57 func (d *datastoreImpl) GetAll(q Query, dst interface{}) error { | 81 func (d *datastoreImpl) GetAll(q Query, dst interface{}) error { |
58 v := reflect.ValueOf(dst) | 82 v := reflect.ValueOf(dst) |
59 if v.Kind() != reflect.Ptr { | 83 if v.Kind() != reflect.Ptr { |
60 return fmt.Errorf("invalid GetAll dst: must have a ptr-to-slice:
%T", dst) | 84 return fmt.Errorf("invalid GetAll dst: must have a ptr-to-slice:
%T", dst) |
61 } | 85 } |
62 if !v.IsValid() || v.IsNil() { | 86 if !v.IsValid() || v.IsNil() { |
63 return errors.New("invalid GetAll dst: <nil>") | 87 return errors.New("invalid GetAll dst: <nil>") |
64 } | 88 } |
65 | 89 |
66 if keys, ok := dst.(*[]Key); ok { | 90 if keys, ok := dst.(*[]Key); ok { |
67 » » return d.RawInterface.Run(q.KeysOnly(), func(k Key, _ PropertyMa
p, _ func() (Cursor, error)) bool { | 91 » » return d.RawInterface.Run(q.KeysOnly(), func(k Key, _ PropertyMa
p, _ CursorCB) bool { |
68 *keys = append(*keys, k) | 92 *keys = append(*keys, k) |
69 return true | 93 return true |
70 }) | 94 }) |
71 } | 95 } |
72 | 96 |
73 slice := v.Elem() | 97 slice := v.Elem() |
74 mat := parseMultiArg(slice.Type()) | 98 mat := parseMultiArg(slice.Type()) |
75 if !mat.valid || mat.newElem == nil { | 99 if !mat.valid || mat.newElem == nil { |
76 return fmt.Errorf("invalid GetAll input type: %T", dst) | 100 return fmt.Errorf("invalid GetAll input type: %T", dst) |
77 } | 101 } |
78 | 102 |
79 lme := errors.LazyMultiError{Size: slice.Len()} | 103 lme := errors.LazyMultiError{Size: slice.Len()} |
80 i := 0 | 104 i := 0 |
81 » err := d.RawInterface.Run(q, func(k Key, pm PropertyMap, _ func() (Curso
r, error)) bool { | 105 » err := d.RawInterface.Run(q, func(k Key, pm PropertyMap, _ CursorCB) boo
l { |
82 slice.Set(reflect.Append(slice, mat.newElem())) | 106 slice.Set(reflect.Append(slice, mat.newElem())) |
83 itm := slice.Index(i) | 107 itm := slice.Index(i) |
84 mat.setKey(itm, k) | 108 mat.setKey(itm, k) |
85 lme.Assign(i, mat.setPM(itm, pm)) | 109 lme.Assign(i, mat.setPM(itm, pm)) |
86 i++ | 110 i++ |
87 return true | 111 return true |
88 }) | 112 }) |
89 if err == nil { | 113 if err == nil { |
90 err = lme.Get() | 114 err = lme.Get() |
91 } | 115 } |
(...skipping 94 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
186 err = lme.Get() | 210 err = lme.Get() |
187 if err == nil { | 211 if err == nil { |
188 err = extErr | 212 err = extErr |
189 } | 213 } |
190 return | 214 return |
191 } | 215 } |
192 | 216 |
193 func (d *datastoreImpl) Raw() RawInterface { | 217 func (d *datastoreImpl) Raw() RawInterface { |
194 return d.RawInterface | 218 return d.RawInterface |
195 } | 219 } |
OLD | NEW |