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 |
| (...skipping 26 matching lines...) Expand all Loading... | |
| 37 } | 37 } |
| 38 | 38 |
| 39 func (d *datastoreImpl) NewKey(kind, stringID string, intID int64, parent *Key) *Key { | 39 func (d *datastoreImpl) NewKey(kind, stringID string, intID int64, parent *Key) *Key { |
| 40 return NewKey(d.aid, d.ns, kind, stringID, intID, parent) | 40 return NewKey(d.aid, d.ns, kind, stringID, intID, parent) |
| 41 } | 41 } |
| 42 | 42 |
| 43 func (d *datastoreImpl) NewKeyToks(toks []KeyTok) *Key { | 43 func (d *datastoreImpl) NewKeyToks(toks []KeyTok) *Key { |
| 44 return NewKeyToks(d.aid, d.ns, toks) | 44 return NewKeyToks(d.aid, d.ns, toks) |
| 45 } | 45 } |
| 46 | 46 |
| 47 func (d *datastoreImpl) Run(q *Query, cbIface interface{}) error { | 47 func runParseCallback(cbIface interface{}) (isKey, hasErr, hasCursorCB bool, mat multiArgType) { |
|
dnj
2015/12/14 22:35:03
My overall concern here is that now the only allus
iannucci
2015/12/14 23:03:09
Discussed offline. I'm not a fan of having a metho
| |
| 48 » badSig := func() { | |
| 49 » » panic(fmt.Errorf( | |
| 50 » » » "cb does not match the required callback signature: `%T` != `func(TYPE, [CursorCB]) [error]`", | |
| 51 » » » cbIface)) | |
| 52 » } | |
| 53 | |
| 48 if cbIface == nil { | 54 if cbIface == nil { |
| 49 » » return fmt.Errorf("cannot use nil callback when Running query") | 55 » » badSig() |
| 50 } | 56 } |
| 51 | 57 |
| 52 // TODO(riannucci): Profile and determine if any of this is causing a re al | 58 // TODO(riannucci): Profile and determine if any of this is causing a re al |
| 53 // slowdown. Could potentially cache reflection stuff by cbTyp? | 59 // slowdown. Could potentially cache reflection stuff by cbTyp? |
| 54 cbTyp := reflect.TypeOf(cbIface) | 60 cbTyp := reflect.TypeOf(cbIface) |
| 55 | 61 |
| 56 » badSig := false | 62 » if cbTyp.Kind() != reflect.Func { |
| 57 » mat := multiArgType{} | 63 » » badSig() |
| 58 » isKey := false | |
| 59 | |
| 60 » if cbTyp.Kind() == reflect.Func && cbTyp.NumIn() == 2 && cbTyp.NumOut() == 1 { | |
| 61 » » firstArg := cbTyp.In(0) | |
| 62 » » if firstArg == typeOfKey { | |
| 63 » » » isKey = true | |
| 64 » » } else { | |
| 65 » » » mat = parseArg(firstArg, false) | |
| 66 » » » badSig = mat.newElem == nil | |
| 67 » » } | |
| 68 » } else { | |
| 69 » » badSig = true | |
| 70 } | 64 } |
| 71 | 65 |
| 72 » if badSig || cbTyp.Out(0) != typeOfBool || cbTyp.In(1) != typeOfCursorCB { | 66 » numIn := cbTyp.NumIn() |
| 73 » » panic(fmt.Errorf( | 67 » if numIn != 1 && numIn != 2 { |
| 74 » » » "cb does not match the required callback signature: `%T` != `func(TYPE, CursorCB) bool`", | 68 » » badSig() |
| 75 » » » cbIface)) | |
| 76 } | 69 } |
| 77 | 70 |
| 78 » if isKey { | 71 » firstArg := cbTyp.In(0) |
| 79 » » cb := cbIface.(func(*Key, CursorCB) bool) | 72 » if firstArg == typeOfKey { |
| 80 » » fq, err := q.KeysOnly(true).Finalize() | 73 » » isKey = true |
| 81 » » if err != nil { | 74 » } else { |
| 82 » » » return err | 75 » » mat = parseArg(firstArg, false) |
| 76 » » if mat.newElem == nil { | |
| 77 » » » badSig() | |
| 83 } | 78 } |
| 84 return d.RawInterface.Run(fq, func(k *Key, _ PropertyMap, gc Cur sorCB) bool { | |
| 85 return cb(k, gc) | |
| 86 }) | |
| 87 } | 79 } |
| 88 | 80 |
| 81 hasCursorCB = numIn == 2 | |
| 82 if hasCursorCB && cbTyp.In(1) != typeOfCursorCB { | |
| 83 badSig() | |
| 84 } | |
| 85 | |
| 86 if cbTyp.NumOut() > 1 { | |
| 87 badSig() | |
| 88 } else if cbTyp.NumOut() == 1 && cbTyp.Out(0) != typeOfError { | |
| 89 badSig() | |
| 90 } | |
| 91 hasErr = cbTyp.NumOut() == 1 | |
| 92 | |
| 93 return | |
| 94 } | |
| 95 | |
| 96 func (d *datastoreImpl) Run(q *Query, cbIface interface{}) error { | |
| 97 isKey, hasErr, hasCursorCB, mat := runParseCallback(cbIface) | |
| 98 | |
| 99 if isKey { | |
| 100 q = q.KeysOnly(true) | |
| 101 } | |
| 89 fq, err := q.Finalize() | 102 fq, err := q.Finalize() |
| 90 if err != nil { | 103 if err != nil { |
| 91 return err | 104 return err |
| 92 } | 105 } |
| 93 | 106 |
| 94 cbVal := reflect.ValueOf(cbIface) | 107 cbVal := reflect.ValueOf(cbIface) |
| 108 var cb func(reflect.Value, CursorCB) error | |
|
dnj
2015/12/14 22:35:03
Either:
(a) Organize this more hierarchically:
if
iannucci
2015/12/14 23:03:09
switch! done!
| |
| 109 if hasErr && hasCursorCB { | |
| 110 cb = func(v reflect.Value, cb CursorCB) error { | |
| 111 err := cbVal.Call([]reflect.Value{v, reflect.ValueOf(cb) })[0].Interface() | |
| 112 if err != nil { | |
| 113 return err.(error) | |
| 114 } | |
| 115 return nil | |
| 116 } | |
| 117 } else if hasErr && !hasCursorCB { | |
| 118 cb = func(v reflect.Value, _ CursorCB) error { | |
| 119 err := cbVal.Call([]reflect.Value{v})[0].Interface() | |
| 120 if err != nil { | |
| 121 return err.(error) | |
| 122 } | |
| 123 return nil | |
| 124 } | |
| 125 } else if !hasErr && hasCursorCB { | |
| 126 cb = func(v reflect.Value, cb CursorCB) error { | |
| 127 cbVal.Call([]reflect.Value{v, reflect.ValueOf(cb)}) | |
| 128 return nil | |
| 129 } | |
| 130 } else if !hasErr && !hasCursorCB { | |
| 131 cb = func(v reflect.Value, _ CursorCB) error { | |
| 132 cbVal.Call([]reflect.Value{v}) | |
| 133 return nil | |
| 134 } | |
| 135 } | |
| 95 | 136 |
| 96 » innerErr := error(nil) | 137 » if isKey { |
| 97 » err = d.RawInterface.Run(fq, func(k *Key, pm PropertyMap, gc CursorCB) b ool { | 138 » » return d.RawInterface.Run(fq, func(k *Key, _ PropertyMap, gc Cur sorCB) error { |
| 139 » » » return cb(reflect.ValueOf(k), gc) | |
| 140 » » }) | |
| 141 » } | |
| 142 | |
| 143 » return d.RawInterface.Run(fq, func(k *Key, pm PropertyMap, gc CursorCB) error { | |
| 98 itm := mat.newElem() | 144 itm := mat.newElem() |
| 99 » » if innerErr = mat.setPM(itm, pm); innerErr != nil { | 145 » » if err := mat.setPM(itm, pm); err != nil { |
| 100 » » » return false | 146 » » » return err |
| 101 } | 147 } |
| 102 mat.setKey(itm, k) | 148 mat.setKey(itm, k) |
| 103 » » return cbVal.Call([]reflect.Value{itm, reflect.ValueOf(gc)})[0]. Bool() | 149 » » return cb(itm, gc) |
| 104 }) | 150 }) |
| 105 if err == nil { | |
| 106 err = innerErr | |
| 107 } | |
| 108 return err | |
| 109 } | 151 } |
| 110 | 152 |
| 111 func (d *datastoreImpl) Count(q *Query) (int64, error) { | 153 func (d *datastoreImpl) Count(q *Query) (int64, error) { |
| 112 fq, err := q.Finalize() | 154 fq, err := q.Finalize() |
| 113 if err != nil { | 155 if err != nil { |
| 114 return 0, err | 156 return 0, err |
| 115 } | 157 } |
| 116 return d.RawInterface.Count(fq) | 158 return d.RawInterface.Count(fq) |
| 117 } | 159 } |
| 118 | 160 |
| 119 func (d *datastoreImpl) GetAll(q *Query, dst interface{}) error { | 161 func (d *datastoreImpl) GetAll(q *Query, dst interface{}) error { |
| 120 v := reflect.ValueOf(dst) | 162 v := reflect.ValueOf(dst) |
| 121 if v.Kind() != reflect.Ptr { | 163 if v.Kind() != reflect.Ptr { |
| 122 return fmt.Errorf("invalid GetAll dst: must have a ptr-to-slice: %T", dst) | 164 return fmt.Errorf("invalid GetAll dst: must have a ptr-to-slice: %T", dst) |
| 123 } | 165 } |
| 124 if !v.IsValid() || v.IsNil() { | 166 if !v.IsValid() || v.IsNil() { |
| 125 return errors.New("invalid GetAll dst: <nil>") | 167 return errors.New("invalid GetAll dst: <nil>") |
| 126 } | 168 } |
| 127 | 169 |
| 128 if keys, ok := dst.(*[]*Key); ok { | 170 if keys, ok := dst.(*[]*Key); ok { |
| 129 fq, err := q.KeysOnly(true).Finalize() | 171 fq, err := q.KeysOnly(true).Finalize() |
| 130 if err != nil { | 172 if err != nil { |
| 131 return err | 173 return err |
| 132 } | 174 } |
| 133 | 175 |
| 134 » » return d.RawInterface.Run(fq, func(k *Key, _ PropertyMap, _ Curs orCB) bool { | 176 » » return d.RawInterface.Run(fq, func(k *Key, _ PropertyMap, _ Curs orCB) error { |
| 135 *keys = append(*keys, k) | 177 *keys = append(*keys, k) |
| 136 » » » return true | 178 » » » return nil |
| 137 }) | 179 }) |
| 138 } | 180 } |
| 139 fq, err := q.Finalize() | 181 fq, err := q.Finalize() |
| 140 if err != nil { | 182 if err != nil { |
| 141 return err | 183 return err |
| 142 } | 184 } |
| 143 | 185 |
| 144 slice := v.Elem() | 186 slice := v.Elem() |
| 145 mat := parseMultiArg(slice.Type()) | 187 mat := parseMultiArg(slice.Type()) |
| 146 if mat.newElem == nil { | 188 if mat.newElem == nil { |
| 147 return fmt.Errorf("invalid GetAll input type: %T", dst) | 189 return fmt.Errorf("invalid GetAll input type: %T", dst) |
| 148 } | 190 } |
| 149 | 191 |
| 150 errs := map[int]error{} | 192 errs := map[int]error{} |
| 151 i := 0 | 193 i := 0 |
| 152 » err = d.RawInterface.Run(fq, func(k *Key, pm PropertyMap, _ CursorCB) bo ol { | 194 » err = d.RawInterface.Run(fq, func(k *Key, pm PropertyMap, _ CursorCB) er ror { |
| 153 slice.Set(reflect.Append(slice, mat.newElem())) | 195 slice.Set(reflect.Append(slice, mat.newElem())) |
| 154 itm := slice.Index(i) | 196 itm := slice.Index(i) |
| 155 mat.setKey(itm, k) | 197 mat.setKey(itm, k) |
| 156 err := mat.setPM(itm, pm) | 198 err := mat.setPM(itm, pm) |
| 157 if err != nil { | 199 if err != nil { |
| 158 errs[i] = err | 200 errs[i] = err |
| 159 } | 201 } |
| 160 i++ | 202 i++ |
| 161 » » return true | 203 » » return nil |
| 162 }) | 204 }) |
| 163 if err == nil { | 205 if err == nil { |
| 164 if len(errs) > 0 { | 206 if len(errs) > 0 { |
| 165 me := make(errors.MultiError, slice.Len()) | 207 me := make(errors.MultiError, slice.Len()) |
| 166 for i, e := range errs { | 208 for i, e := range errs { |
| 167 me[i] = e | 209 me[i] = e |
| 168 } | 210 } |
| 169 err = me | 211 err = me |
| 170 } | 212 } |
| 171 } | 213 } |
| 172 return err | 214 return err |
| 173 } | 215 } |
| 174 | 216 |
| 175 func isOkType(v reflect.Type) bool { | 217 func isOkType(v reflect.Type) bool { |
| 176 if v.Implements(typeOfPropertyLoadSaver) { | 218 if v.Implements(typeOfPropertyLoadSaver) { |
| 177 return true | 219 return true |
| 178 } | 220 } |
| 179 if v.Kind() == reflect.Ptr && v.Elem().Kind() == reflect.Struct { | 221 if v.Kind() == reflect.Ptr && v.Elem().Kind() == reflect.Struct { |
| 180 return true | 222 return true |
| 181 } | 223 } |
| 182 return false | 224 return false |
| 183 } | 225 } |
| 184 | 226 |
| 185 func (d *datastoreImpl) ExistsMulti(keys []*Key) ([]bool, error) { | 227 func (d *datastoreImpl) ExistsMulti(keys []*Key) ([]bool, error) { |
| 186 lme := errors.NewLazyMultiError(len(keys)) | 228 lme := errors.NewLazyMultiError(len(keys)) |
| 187 ret := make([]bool, len(keys)) | 229 ret := make([]bool, len(keys)) |
| 188 i := 0 | 230 i := 0 |
| 189 » err := d.RawInterface.GetMulti(keys, nil, func(_ PropertyMap, err error) { | 231 » err := d.RawInterface.GetMulti(keys, nil, func(_ PropertyMap, err error) error { |
| 190 if err == nil { | 232 if err == nil { |
| 191 ret[i] = true | 233 ret[i] = true |
| 192 } else if err != ErrNoSuchEntity { | 234 } else if err != ErrNoSuchEntity { |
| 193 lme.Assign(i, err) | 235 lme.Assign(i, err) |
| 194 } | 236 } |
| 195 i++ | 237 i++ |
| 238 return nil | |
| 196 }) | 239 }) |
| 197 if err != nil { | 240 if err != nil { |
| 198 return ret, err | 241 return ret, err |
| 199 } | 242 } |
| 200 return ret, lme.Get() | 243 return ret, lme.Get() |
| 201 } | 244 } |
| 202 | 245 |
| 203 func (d *datastoreImpl) Exists(k *Key) (bool, error) { | 246 func (d *datastoreImpl) Exists(k *Key) (bool, error) { |
| 204 ret, err := d.ExistsMulti([]*Key{k}) | 247 ret, err := d.ExistsMulti([]*Key{k}) |
| 205 return ret[0], errors.SingleError(err) | 248 return ret[0], errors.SingleError(err) |
| (...skipping 22 matching lines...) Expand all Loading... | |
| 228 mat := parseMultiArg(slice.Type()) | 271 mat := parseMultiArg(slice.Type()) |
| 229 | 272 |
| 230 keys, pms, err := mat.GetKeysPMs(d.aid, d.ns, slice, true) | 273 keys, pms, err := mat.GetKeysPMs(d.aid, d.ns, slice, true) |
| 231 if err != nil { | 274 if err != nil { |
| 232 return err | 275 return err |
| 233 } | 276 } |
| 234 | 277 |
| 235 lme := errors.NewLazyMultiError(len(keys)) | 278 lme := errors.NewLazyMultiError(len(keys)) |
| 236 i := 0 | 279 i := 0 |
| 237 meta := NewMultiMetaGetter(pms) | 280 meta := NewMultiMetaGetter(pms) |
| 238 » err = d.RawInterface.GetMulti(keys, meta, func(pm PropertyMap, err error ) { | 281 » err = d.RawInterface.GetMulti(keys, meta, func(pm PropertyMap, err error ) error { |
| 239 if !lme.Assign(i, err) { | 282 if !lme.Assign(i, err) { |
| 240 lme.Assign(i, mat.setPM(slice.Index(i), pm)) | 283 lme.Assign(i, mat.setPM(slice.Index(i), pm)) |
| 241 } | 284 } |
| 242 i++ | 285 i++ |
| 286 return nil | |
| 243 }) | 287 }) |
| 244 | 288 |
| 245 if err == nil { | 289 if err == nil { |
| 246 err = lme.Get() | 290 err = lme.Get() |
| 247 } | 291 } |
| 248 return err | 292 return err |
| 249 } | 293 } |
| 250 | 294 |
| 251 func (d *datastoreImpl) PutMulti(src interface{}) error { | 295 func (d *datastoreImpl) PutMulti(src interface{}) error { |
| 252 slice := reflect.ValueOf(src) | 296 slice := reflect.ValueOf(src) |
| 253 mat := parseMultiArg(slice.Type()) | 297 mat := parseMultiArg(slice.Type()) |
| 254 | 298 |
| 255 keys, vals, err := mat.GetKeysPMs(d.aid, d.ns, slice, false) | 299 keys, vals, err := mat.GetKeysPMs(d.aid, d.ns, slice, false) |
| 256 if err != nil { | 300 if err != nil { |
| 257 return err | 301 return err |
| 258 } | 302 } |
| 259 | 303 |
| 260 lme := errors.NewLazyMultiError(len(keys)) | 304 lme := errors.NewLazyMultiError(len(keys)) |
| 261 i := 0 | 305 i := 0 |
| 262 » err = d.RawInterface.PutMulti(keys, vals, func(key *Key, err error) { | 306 » err = d.RawInterface.PutMulti(keys, vals, func(key *Key, err error) erro r { |
| 263 if key != keys[i] { | 307 if key != keys[i] { |
| 264 mat.setKey(slice.Index(i), key) | 308 mat.setKey(slice.Index(i), key) |
| 265 } | 309 } |
| 266 lme.Assign(i, err) | 310 lme.Assign(i, err) |
| 267 i++ | 311 i++ |
| 312 return nil | |
| 268 }) | 313 }) |
| 269 | 314 |
| 270 if err == nil { | 315 if err == nil { |
| 271 err = lme.Get() | 316 err = lme.Get() |
| 272 } | 317 } |
| 273 return err | 318 return err |
| 274 } | 319 } |
| 275 | 320 |
| 276 func (d *datastoreImpl) DeleteMulti(keys []*Key) (err error) { | 321 func (d *datastoreImpl) DeleteMulti(keys []*Key) (err error) { |
| 277 lme := errors.NewLazyMultiError(len(keys)) | 322 lme := errors.NewLazyMultiError(len(keys)) |
| 278 i := 0 | 323 i := 0 |
| 279 » extErr := d.RawInterface.DeleteMulti(keys, func(internalErr error) { | 324 » extErr := d.RawInterface.DeleteMulti(keys, func(internalErr error) error { |
| 280 lme.Assign(i, internalErr) | 325 lme.Assign(i, internalErr) |
| 281 i++ | 326 i++ |
| 327 return nil | |
| 282 }) | 328 }) |
| 283 err = lme.Get() | 329 err = lme.Get() |
| 284 if err == nil { | 330 if err == nil { |
| 285 err = extErr | 331 err = extErr |
| 286 } | 332 } |
| 287 return | 333 return |
| 288 } | 334 } |
| 289 | 335 |
| 290 func (d *datastoreImpl) Raw() RawInterface { | 336 func (d *datastoreImpl) Raw() RawInterface { |
| 291 return d.RawInterface | 337 return d.RawInterface |
| 292 } | 338 } |
| OLD | NEW |