OLD | NEW |
---|---|
(Empty) | |
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 | |
3 // found in the LICENSE file. | |
4 | |
5 package datastore | |
6 | |
7 import ( | |
8 "fmt" | |
9 "reflect" | |
10 | |
11 "github.com/luci/luci-go/common/errors" | |
12 ) | |
13 | |
14 type datastoreImpl struct{ RawInterface } | |
15 | |
16 var _ Interface = (*datastoreImpl)(nil) | |
17 | |
18 func (d *datastoreImpl) NewKeyObj(src interface{}) Key { | |
19 ret, err := d.NewKeyObjErr(src) | |
20 if err != nil { | |
21 panic(err) | |
22 } | |
23 return ret | |
24 } | |
25 | |
26 func (d *datastoreImpl) NewKeyObjErr(src interface{}) (Key, error) { | |
27 return newKeyObjErr(d.NewKey, src) | |
28 } | |
29 | |
30 func (d *datastoreImpl) Run(q Query, proto interface{}, cb RunCB) error { | |
31 if _, ok := proto.(*Key); ok { | |
32 return d.RawInterface.Run(q.KeysOnly(), func(k Key, _ PropertyMa p, gc func() (Cursor, error)) bool { | |
33 return cb(k, gc) | |
34 }) | |
35 } | |
36 | |
37 t := reflect.TypeOf(proto) | |
38 if t.Kind() != reflect.Ptr { | |
39 return fmt.Errorf("invalid Run proto type: %T", proto) | |
40 } | |
41 e := t.Elem() | |
42 var mkPLS func() (interface{}, PropertyLoadSaver) | |
43 if t.Implements(typeOfPropertyLoadSaver) { | |
44 mkPLS = func() (interface{}, PropertyLoadSaver) { | |
45 iface := reflect.New(e).Interface() | |
46 return iface, iface.(PropertyLoadSaver) | |
47 } | |
48 } else if e.Kind() == reflect.Struct { | |
49 cdc := getCodec(e) | |
50 mkPLS = func() (interface{}, PropertyLoadSaver) { | |
51 ptr := reflect.New(e) | |
52 return ptr.Interface(), &structPLS{ptr.Elem(), cdc} | |
53 } | |
54 } | |
55 if mkPLS == nil { | |
56 return fmt.Errorf("invalid Run proto type: %T", proto) | |
57 } | |
58 | |
59 innerErr := error(nil) | |
60 err := d.RawInterface.Run(q, func(k Key, pm PropertyMap, gc func() (Curs or, error)) bool { | |
61 iface, pls := mkPLS() | |
62 if innerErr = pls.Load(pm); innerErr != nil { | |
63 return false | |
64 } | |
65 setKey(pls, k) | |
66 return cb(iface, gc) | |
67 }) | |
68 if err == nil { | |
69 err = innerErr | |
Vadim Sh.
2015/07/29 16:21:43
are you sure you want to return error(nil) instead
iannucci
2015/08/03 03:56:31
pretty sure it's the same thing. `innerErr := err
| |
70 } | |
71 return err | |
72 } | |
73 | |
74 func (d *datastoreImpl) GetAll(q Query, dst interface{}) error { | |
75 v := reflect.ValueOf(dst) | |
76 if v.IsNil() { | |
77 return errors.New("invalid GetAll dst: <nil>") | |
78 } | |
79 | |
80 t := v.Type() | |
81 if t.Kind() != reflect.Ptr || t.Elem().Kind() != reflect.Slice { | |
82 return fmt.Errorf("invalid GetAll dst: must have a ptr-to-slice %T", dst) | |
83 } | |
84 | |
85 if keys, ok := dst.(*[]Key); ok { | |
86 return d.RawInterface.Run(q.KeysOnly(), func(k Key, _ PropertyMa p, _ func() (Cursor, error)) bool { | |
87 *keys = append(*keys, k) | |
88 return true | |
89 }) | |
90 } | |
91 | |
92 slice := v.Elem() | |
93 mat := parseArg(t.Elem()) | |
94 if !mat.valid || mat.newElem == nil { | |
95 return fmt.Errorf("invalid GetAll input type: %T", dst) | |
96 } | |
97 | |
98 lme := errors.LazyMultiError{Size: slice.Len()} | |
99 i := 0 | |
100 err := d.RawInterface.Run(q, func(k Key, pm PropertyMap, _ func() (Curso r, error)) bool { | |
101 itm := mat.newElem() | |
102 slice.Set(reflect.Append(slice, itm)) | |
103 mat.setKey(itm, k) | |
104 lme.Assign(i, mat.setPM(itm, pm)) | |
105 i++ | |
106 return true | |
107 }) | |
108 if err == nil { | |
109 err = lme.Get() | |
110 } | |
111 return err | |
112 } | |
113 | |
114 func (d *datastoreImpl) Get(dst interface{}) (err error) { | |
115 return errors.SingleError(d.GetMulti([]interface{}{dst})) | |
116 } | |
117 | |
118 func (d *datastoreImpl) Put(src interface{}) (err error) { | |
119 return errors.SingleError(d.PutMulti([]interface{}{src})) | |
120 } | |
121 | |
122 func (d *datastoreImpl) Delete(key Key) (err error) { | |
123 return errors.SingleError(d.DeleteMulti([]Key{key})) | |
124 } | |
125 | |
126 func (d *datastoreImpl) GetMulti(dst interface{}) error { | |
127 slice := reflect.ValueOf(dst) | |
128 mat := parseMultiArg(slice.Type()) | |
129 if !mat.valid { | |
130 return fmt.Errorf("invalid GetMulti input type: %T", dst) | |
131 } | |
132 | |
133 keys, err := mat.GetKeys(d.NewKey, slice) | |
134 if err != nil { | |
135 return err | |
136 } | |
137 | |
138 lme := errors.LazyMultiError{Size: len(keys)} | |
139 i := 0 | |
140 err = d.RawInterface.GetMulti(keys, func(pm PropertyMap, err error) { | |
141 if !lme.Assign(i, err) { | |
142 lme.Assign(i, mat.setPM(slice.Index(i), pm)) | |
143 } | |
144 i++ | |
145 }) | |
146 | |
147 if err == nil { | |
148 err = lme.Get() | |
149 } | |
150 return err | |
151 } | |
152 | |
153 func (d *datastoreImpl) PutMulti(src interface{}) error { | |
154 slice := reflect.ValueOf(src) | |
155 mat := parseMultiArg(slice.Type()) | |
156 if !mat.valid { | |
157 return fmt.Errorf("invalid PutMulti input type: %T", src) | |
158 } | |
159 | |
160 keys, err := mat.GetKeys(d.NewKey, slice) | |
161 if err != nil { | |
162 return err | |
163 } | |
164 | |
165 vals, err := mat.GetPMs(slice) | |
166 if err != nil { | |
167 return err | |
168 } | |
169 | |
170 lme := errors.LazyMultiError{Size: len(keys)} | |
171 i := 0 | |
172 err = d.RawInterface.PutMulti(keys, vals, func(key Key, err error) { | |
173 mat.setKey(slice.Index(i), key) | |
174 lme.Assign(i, err) | |
175 i++ | |
176 }) | |
177 | |
178 if err == nil { | |
179 err = lme.Get() | |
180 } | |
181 return err | |
182 } | |
183 | |
184 func (d *datastoreImpl) DeleteMulti(keys []Key) (err error) { | |
185 lme := errors.LazyMultiError{Size: len(keys)} | |
186 i := 0 | |
187 extErr := d.RawInterface.DeleteMulti(keys, func(internalErr error) { | |
188 lme.Assign(i, internalErr) | |
189 i++ | |
190 }) | |
191 err = lme.Get() | |
192 if err == nil { | |
193 err = extErr | |
194 } | |
195 return | |
196 } | |
197 | |
198 func (d *datastoreImpl) Raw() RawInterface { | |
199 return d.RawInterface | |
200 } | |
OLD | NEW |