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 » cbTyp := reflect.TypeOf(cbIface) |
32 » » return d.RawInterface.Run(q.KeysOnly(), func(k Key, _ PropertyMa p, gc func() (Cursor, error)) bool { | 32 » if cbTyp.NumIn() != 2 || cbTyp.NumOut() != 1 { |
Vadim Sh.
2015/08/07 20:23:05
check that cbTyp is a function?
iannucci
2015/08/07 20:37:50
Done.
| |
33 » » return fmt.Errorf("cb has the wrong number of args: %T", cbIface ) | |
34 » } | |
35 | |
36 » if cbTyp.Out(0) != typeOfBool { | |
37 » » return fmt.Errorf("cb has the wrong return type (expected bool): %s", cbTyp.Out(0)) | |
38 » } | |
39 | |
40 » if cbTyp.In(1) != typeOfCursorCB { | |
41 » » return fmt.Errorf("cb has a bad second argument (expected Cursor CB): %s", cbTyp.In(1)) | |
42 » } | |
43 | |
44 » if cbTyp.In(0) == typeOfKey { | |
Vadim Sh.
2015/08/07 20:23:05
nit: you can probably cache all this checks (using
iannucci
2015/08/07 20:37:50
Yeah, probably can. I suspect it's overkill though
iannucci
2015/08/07 20:37:50
Yeah, probably can. I suspect it's overkill though
| |
45 » » cb := cbIface.(func(Key, CursorCB) bool) | |
46 » » return d.RawInterface.Run(q.KeysOnly(), func(k Key, _ PropertyMa p, gc CursorCB) bool { | |
33 return cb(k, gc) | 47 return cb(k, gc) |
34 }) | 48 }) |
35 } | 49 } |
36 | 50 |
37 » mat := parseArg(reflect.TypeOf(proto)) | 51 » mat := parseArg(cbTyp.In(0)) |
38 if !mat.valid || mat.newElem == nil { | 52 if !mat.valid || mat.newElem == nil { |
39 » » return fmt.Errorf("invalid Run proto type: %T", proto) | 53 » » return fmt.Errorf("cb has a bad first argument: %s", cbTyp.In(0) ) |
40 } | 54 } |
55 cbVal := reflect.ValueOf(cbIface) | |
41 | 56 |
42 innerErr := error(nil) | 57 innerErr := error(nil) |
43 » err := d.RawInterface.Run(q, func(k Key, pm PropertyMap, gc func() (Curs or, error)) bool { | 58 » err := d.RawInterface.Run(q, func(k Key, pm PropertyMap, gc CursorCB) bo ol { |
44 itm := mat.newElem() | 59 itm := mat.newElem() |
45 if innerErr = mat.setPM(itm, pm); innerErr != nil { | 60 if innerErr = mat.setPM(itm, pm); innerErr != nil { |
46 return false | 61 return false |
47 } | 62 } |
48 mat.setKey(itm, k) | 63 mat.setKey(itm, k) |
49 » » return cb(itm.Interface(), gc) | 64 » » return cbVal.Call([]reflect.Value{itm, reflect.ValueOf(gc)})[0]. Bool() |
50 }) | 65 }) |
51 if err == nil { | 66 if err == nil { |
52 err = innerErr | 67 err = innerErr |
53 } | 68 } |
54 return err | 69 return err |
55 } | 70 } |
56 | 71 |
57 func (d *datastoreImpl) GetAll(q Query, dst interface{}) error { | 72 func (d *datastoreImpl) GetAll(q Query, dst interface{}) error { |
58 v := reflect.ValueOf(dst) | 73 v := reflect.ValueOf(dst) |
59 if v.Kind() != reflect.Ptr { | 74 if v.Kind() != reflect.Ptr { |
60 return fmt.Errorf("invalid GetAll dst: must have a ptr-to-slice: %T", dst) | 75 return fmt.Errorf("invalid GetAll dst: must have a ptr-to-slice: %T", dst) |
61 } | 76 } |
62 if !v.IsValid() || v.IsNil() { | 77 if !v.IsValid() || v.IsNil() { |
63 return errors.New("invalid GetAll dst: <nil>") | 78 return errors.New("invalid GetAll dst: <nil>") |
64 } | 79 } |
65 | 80 |
66 if keys, ok := dst.(*[]Key); ok { | 81 if keys, ok := dst.(*[]Key); ok { |
67 » » return d.RawInterface.Run(q.KeysOnly(), func(k Key, _ PropertyMa p, _ func() (Cursor, error)) bool { | 82 » » return d.RawInterface.Run(q.KeysOnly(), func(k Key, _ PropertyMa p, _ CursorCB) bool { |
68 *keys = append(*keys, k) | 83 *keys = append(*keys, k) |
69 return true | 84 return true |
70 }) | 85 }) |
71 } | 86 } |
72 | 87 |
73 slice := v.Elem() | 88 slice := v.Elem() |
74 mat := parseMultiArg(slice.Type()) | 89 mat := parseMultiArg(slice.Type()) |
75 if !mat.valid || mat.newElem == nil { | 90 if !mat.valid || mat.newElem == nil { |
76 return fmt.Errorf("invalid GetAll input type: %T", dst) | 91 return fmt.Errorf("invalid GetAll input type: %T", dst) |
77 } | 92 } |
78 | 93 |
79 lme := errors.LazyMultiError{Size: slice.Len()} | 94 lme := errors.LazyMultiError{Size: slice.Len()} |
80 i := 0 | 95 i := 0 |
81 » err := d.RawInterface.Run(q, func(k Key, pm PropertyMap, _ func() (Curso r, error)) bool { | 96 » err := d.RawInterface.Run(q, func(k Key, pm PropertyMap, _ CursorCB) boo l { |
82 slice.Set(reflect.Append(slice, mat.newElem())) | 97 slice.Set(reflect.Append(slice, mat.newElem())) |
83 itm := slice.Index(i) | 98 itm := slice.Index(i) |
84 mat.setKey(itm, k) | 99 mat.setKey(itm, k) |
85 lme.Assign(i, mat.setPM(itm, pm)) | 100 lme.Assign(i, mat.setPM(itm, pm)) |
86 i++ | 101 i++ |
87 return true | 102 return true |
88 }) | 103 }) |
89 if err == nil { | 104 if err == nil { |
90 err = lme.Get() | 105 err = lme.Get() |
91 } | 106 } |
(...skipping 94 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
186 err = lme.Get() | 201 err = lme.Get() |
187 if err == nil { | 202 if err == nil { |
188 err = extErr | 203 err = extErr |
189 } | 204 } |
190 return | 205 return |
191 } | 206 } |
192 | 207 |
193 func (d *datastoreImpl) Raw() RawInterface { | 208 func (d *datastoreImpl) Raw() RawInterface { |
194 return d.RawInterface | 209 return d.RawInterface |
195 } | 210 } |
OLD | NEW |