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 |