Chromium Code Reviews| 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 |