| 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) { |
| 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 |
| 109 switch { |
| 110 case hasErr && hasCursorCB: |
| 111 cb = func(v reflect.Value, cb CursorCB) error { |
| 112 err := cbVal.Call([]reflect.Value{v, reflect.ValueOf(cb)
})[0].Interface() |
| 113 if err != nil { |
| 114 return err.(error) |
| 115 } |
| 116 return nil |
| 117 } |
| 95 | 118 |
| 96 » innerErr := error(nil) | 119 » case hasErr && !hasCursorCB: |
| 97 » err = d.RawInterface.Run(fq, func(k *Key, pm PropertyMap, gc CursorCB) b
ool { | 120 » » cb = func(v reflect.Value, _ CursorCB) error { |
| 121 » » » err := cbVal.Call([]reflect.Value{v})[0].Interface() |
| 122 » » » if err != nil { |
| 123 » » » » return err.(error) |
| 124 » » » } |
| 125 » » » return nil |
| 126 » » } |
| 127 |
| 128 » case !hasErr && hasCursorCB: |
| 129 » » cb = func(v reflect.Value, cb CursorCB) error { |
| 130 » » » cbVal.Call([]reflect.Value{v, reflect.ValueOf(cb)}) |
| 131 » » » return nil |
| 132 » » } |
| 133 |
| 134 » case !hasErr && !hasCursorCB: |
| 135 » » cb = func(v reflect.Value, _ CursorCB) error { |
| 136 » » » cbVal.Call([]reflect.Value{v}) |
| 137 » » » return nil |
| 138 » » } |
| 139 » } |
| 140 |
| 141 » if isKey { |
| 142 » » return d.RawInterface.Run(fq, func(k *Key, _ PropertyMap, gc Cur
sorCB) error { |
| 143 » » » return cb(reflect.ValueOf(k), gc) |
| 144 » » }) |
| 145 » } |
| 146 |
| 147 » return d.RawInterface.Run(fq, func(k *Key, pm PropertyMap, gc CursorCB)
error { |
| 98 itm := mat.newElem() | 148 itm := mat.newElem() |
| 99 » » if innerErr = mat.setPM(itm, pm); innerErr != nil { | 149 » » if err := mat.setPM(itm, pm); err != nil { |
| 100 » » » return false | 150 » » » return err |
| 101 } | 151 } |
| 102 mat.setKey(itm, k) | 152 mat.setKey(itm, k) |
| 103 » » return cbVal.Call([]reflect.Value{itm, reflect.ValueOf(gc)})[0].
Bool() | 153 » » return cb(itm, gc) |
| 104 }) | 154 }) |
| 105 if err == nil { | |
| 106 err = innerErr | |
| 107 } | |
| 108 return err | |
| 109 } | 155 } |
| 110 | 156 |
| 111 func (d *datastoreImpl) Count(q *Query) (int64, error) { | 157 func (d *datastoreImpl) Count(q *Query) (int64, error) { |
| 112 fq, err := q.Finalize() | 158 fq, err := q.Finalize() |
| 113 if err != nil { | 159 if err != nil { |
| 114 return 0, err | 160 return 0, err |
| 115 } | 161 } |
| 116 return d.RawInterface.Count(fq) | 162 return d.RawInterface.Count(fq) |
| 117 } | 163 } |
| 118 | 164 |
| 119 func (d *datastoreImpl) GetAll(q *Query, dst interface{}) error { | 165 func (d *datastoreImpl) GetAll(q *Query, dst interface{}) error { |
| 120 v := reflect.ValueOf(dst) | 166 v := reflect.ValueOf(dst) |
| 121 if v.Kind() != reflect.Ptr { | 167 if v.Kind() != reflect.Ptr { |
| 122 return fmt.Errorf("invalid GetAll dst: must have a ptr-to-slice:
%T", dst) | 168 return fmt.Errorf("invalid GetAll dst: must have a ptr-to-slice:
%T", dst) |
| 123 } | 169 } |
| 124 if !v.IsValid() || v.IsNil() { | 170 if !v.IsValid() || v.IsNil() { |
| 125 return errors.New("invalid GetAll dst: <nil>") | 171 return errors.New("invalid GetAll dst: <nil>") |
| 126 } | 172 } |
| 127 | 173 |
| 128 if keys, ok := dst.(*[]*Key); ok { | 174 if keys, ok := dst.(*[]*Key); ok { |
| 129 fq, err := q.KeysOnly(true).Finalize() | 175 fq, err := q.KeysOnly(true).Finalize() |
| 130 if err != nil { | 176 if err != nil { |
| 131 return err | 177 return err |
| 132 } | 178 } |
| 133 | 179 |
| 134 » » return d.RawInterface.Run(fq, func(k *Key, _ PropertyMap, _ Curs
orCB) bool { | 180 » » return d.RawInterface.Run(fq, func(k *Key, _ PropertyMap, _ Curs
orCB) error { |
| 135 *keys = append(*keys, k) | 181 *keys = append(*keys, k) |
| 136 » » » return true | 182 » » » return nil |
| 137 }) | 183 }) |
| 138 } | 184 } |
| 139 fq, err := q.Finalize() | 185 fq, err := q.Finalize() |
| 140 if err != nil { | 186 if err != nil { |
| 141 return err | 187 return err |
| 142 } | 188 } |
| 143 | 189 |
| 144 slice := v.Elem() | 190 slice := v.Elem() |
| 145 mat := parseMultiArg(slice.Type()) | 191 mat := parseMultiArg(slice.Type()) |
| 146 if mat.newElem == nil { | 192 if mat.newElem == nil { |
| 147 return fmt.Errorf("invalid GetAll input type: %T", dst) | 193 return fmt.Errorf("invalid GetAll input type: %T", dst) |
| 148 } | 194 } |
| 149 | 195 |
| 150 errs := map[int]error{} | 196 errs := map[int]error{} |
| 151 i := 0 | 197 i := 0 |
| 152 » err = d.RawInterface.Run(fq, func(k *Key, pm PropertyMap, _ CursorCB) bo
ol { | 198 » err = d.RawInterface.Run(fq, func(k *Key, pm PropertyMap, _ CursorCB) er
ror { |
| 153 slice.Set(reflect.Append(slice, mat.newElem())) | 199 slice.Set(reflect.Append(slice, mat.newElem())) |
| 154 itm := slice.Index(i) | 200 itm := slice.Index(i) |
| 155 mat.setKey(itm, k) | 201 mat.setKey(itm, k) |
| 156 err := mat.setPM(itm, pm) | 202 err := mat.setPM(itm, pm) |
| 157 if err != nil { | 203 if err != nil { |
| 158 errs[i] = err | 204 errs[i] = err |
| 159 } | 205 } |
| 160 i++ | 206 i++ |
| 161 » » return true | 207 » » return nil |
| 162 }) | 208 }) |
| 163 if err == nil { | 209 if err == nil { |
| 164 if len(errs) > 0 { | 210 if len(errs) > 0 { |
| 165 me := make(errors.MultiError, slice.Len()) | 211 me := make(errors.MultiError, slice.Len()) |
| 166 for i, e := range errs { | 212 for i, e := range errs { |
| 167 me[i] = e | 213 me[i] = e |
| 168 } | 214 } |
| 169 err = me | 215 err = me |
| 170 } | 216 } |
| 171 } | 217 } |
| 172 return err | 218 return err |
| 173 } | 219 } |
| 174 | 220 |
| 175 func isOkType(v reflect.Type) bool { | 221 func isOkType(v reflect.Type) bool { |
| 176 if v.Implements(typeOfPropertyLoadSaver) { | 222 if v.Implements(typeOfPropertyLoadSaver) { |
| 177 return true | 223 return true |
| 178 } | 224 } |
| 179 if v.Kind() == reflect.Ptr && v.Elem().Kind() == reflect.Struct { | 225 if v.Kind() == reflect.Ptr && v.Elem().Kind() == reflect.Struct { |
| 180 return true | 226 return true |
| 181 } | 227 } |
| 182 return false | 228 return false |
| 183 } | 229 } |
| 184 | 230 |
| 185 func (d *datastoreImpl) ExistsMulti(keys []*Key) ([]bool, error) { | 231 func (d *datastoreImpl) ExistsMulti(keys []*Key) ([]bool, error) { |
| 186 lme := errors.NewLazyMultiError(len(keys)) | 232 lme := errors.NewLazyMultiError(len(keys)) |
| 187 ret := make([]bool, len(keys)) | 233 ret := make([]bool, len(keys)) |
| 188 i := 0 | 234 i := 0 |
| 189 » err := d.RawInterface.GetMulti(keys, nil, func(_ PropertyMap, err error)
{ | 235 » err := d.RawInterface.GetMulti(keys, nil, func(_ PropertyMap, err error)
error { |
| 190 if err == nil { | 236 if err == nil { |
| 191 ret[i] = true | 237 ret[i] = true |
| 192 } else if err != ErrNoSuchEntity { | 238 } else if err != ErrNoSuchEntity { |
| 193 lme.Assign(i, err) | 239 lme.Assign(i, err) |
| 194 } | 240 } |
| 195 i++ | 241 i++ |
| 242 return nil |
| 196 }) | 243 }) |
| 197 if err != nil { | 244 if err != nil { |
| 198 return ret, err | 245 return ret, err |
| 199 } | 246 } |
| 200 return ret, lme.Get() | 247 return ret, lme.Get() |
| 201 } | 248 } |
| 202 | 249 |
| 203 func (d *datastoreImpl) Exists(k *Key) (bool, error) { | 250 func (d *datastoreImpl) Exists(k *Key) (bool, error) { |
| 204 ret, err := d.ExistsMulti([]*Key{k}) | 251 ret, err := d.ExistsMulti([]*Key{k}) |
| 205 return ret[0], errors.SingleError(err) | 252 return ret[0], errors.SingleError(err) |
| (...skipping 22 matching lines...) Expand all Loading... |
| 228 mat := parseMultiArg(slice.Type()) | 275 mat := parseMultiArg(slice.Type()) |
| 229 | 276 |
| 230 keys, pms, err := mat.GetKeysPMs(d.aid, d.ns, slice, true) | 277 keys, pms, err := mat.GetKeysPMs(d.aid, d.ns, slice, true) |
| 231 if err != nil { | 278 if err != nil { |
| 232 return err | 279 return err |
| 233 } | 280 } |
| 234 | 281 |
| 235 lme := errors.NewLazyMultiError(len(keys)) | 282 lme := errors.NewLazyMultiError(len(keys)) |
| 236 i := 0 | 283 i := 0 |
| 237 meta := NewMultiMetaGetter(pms) | 284 meta := NewMultiMetaGetter(pms) |
| 238 » err = d.RawInterface.GetMulti(keys, meta, func(pm PropertyMap, err error
) { | 285 » err = d.RawInterface.GetMulti(keys, meta, func(pm PropertyMap, err error
) error { |
| 239 if !lme.Assign(i, err) { | 286 if !lme.Assign(i, err) { |
| 240 lme.Assign(i, mat.setPM(slice.Index(i), pm)) | 287 lme.Assign(i, mat.setPM(slice.Index(i), pm)) |
| 241 } | 288 } |
| 242 i++ | 289 i++ |
| 290 return nil |
| 243 }) | 291 }) |
| 244 | 292 |
| 245 if err == nil { | 293 if err == nil { |
| 246 err = lme.Get() | 294 err = lme.Get() |
| 247 } | 295 } |
| 248 return err | 296 return err |
| 249 } | 297 } |
| 250 | 298 |
| 251 func (d *datastoreImpl) PutMulti(src interface{}) error { | 299 func (d *datastoreImpl) PutMulti(src interface{}) error { |
| 252 slice := reflect.ValueOf(src) | 300 slice := reflect.ValueOf(src) |
| 253 mat := parseMultiArg(slice.Type()) | 301 mat := parseMultiArg(slice.Type()) |
| 254 | 302 |
| 255 keys, vals, err := mat.GetKeysPMs(d.aid, d.ns, slice, false) | 303 keys, vals, err := mat.GetKeysPMs(d.aid, d.ns, slice, false) |
| 256 if err != nil { | 304 if err != nil { |
| 257 return err | 305 return err |
| 258 } | 306 } |
| 259 | 307 |
| 260 lme := errors.NewLazyMultiError(len(keys)) | 308 lme := errors.NewLazyMultiError(len(keys)) |
| 261 i := 0 | 309 i := 0 |
| 262 » err = d.RawInterface.PutMulti(keys, vals, func(key *Key, err error) { | 310 » err = d.RawInterface.PutMulti(keys, vals, func(key *Key, err error) erro
r { |
| 263 if key != keys[i] { | 311 if key != keys[i] { |
| 264 mat.setKey(slice.Index(i), key) | 312 mat.setKey(slice.Index(i), key) |
| 265 } | 313 } |
| 266 lme.Assign(i, err) | 314 lme.Assign(i, err) |
| 267 i++ | 315 i++ |
| 316 return nil |
| 268 }) | 317 }) |
| 269 | 318 |
| 270 if err == nil { | 319 if err == nil { |
| 271 err = lme.Get() | 320 err = lme.Get() |
| 272 } | 321 } |
| 273 return err | 322 return err |
| 274 } | 323 } |
| 275 | 324 |
| 276 func (d *datastoreImpl) DeleteMulti(keys []*Key) (err error) { | 325 func (d *datastoreImpl) DeleteMulti(keys []*Key) (err error) { |
| 277 lme := errors.NewLazyMultiError(len(keys)) | 326 lme := errors.NewLazyMultiError(len(keys)) |
| 278 i := 0 | 327 i := 0 |
| 279 » extErr := d.RawInterface.DeleteMulti(keys, func(internalErr error) { | 328 » extErr := d.RawInterface.DeleteMulti(keys, func(internalErr error) error
{ |
| 280 lme.Assign(i, internalErr) | 329 lme.Assign(i, internalErr) |
| 281 i++ | 330 i++ |
| 331 return nil |
| 282 }) | 332 }) |
| 283 err = lme.Get() | 333 err = lme.Get() |
| 284 if err == nil { | 334 if err == nil { |
| 285 err = extErr | 335 err = extErr |
| 286 } | 336 } |
| 287 return | 337 return |
| 288 } | 338 } |
| 289 | 339 |
| 290 func (d *datastoreImpl) Raw() RawInterface { | 340 func (d *datastoreImpl) Raw() RawInterface { |
| 291 return d.RawInterface | 341 return d.RawInterface |
| 292 } | 342 } |
| OLD | NEW |