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 |