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) KeyForObj(src interface{}) Key { | |
19 ret, err := d.KeyForObjErr(src) | |
20 if err != nil { | |
21 panic(err) | |
22 } | |
23 return ret | |
24 } | |
25 | |
26 func (d *datastoreImpl) KeyForObjErr(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 mat := parseArg(reflect.TypeOf(proto)) | |
38 if !mat.valid || mat.newElem == nil { | |
39 return fmt.Errorf("invalid Run proto type: %T", proto) | |
40 } | |
41 | |
42 innerErr := error(nil) | |
43 err := d.RawInterface.Run(q, func(k Key, pm PropertyMap, gc func() (Curs or, error)) bool { | |
44 itm := mat.newElem() | |
45 if innerErr = mat.setPM(itm, pm); innerErr != nil { | |
46 return false | |
47 } | |
48 mat.setKey(itm, k) | |
49 return cb(itm.Interface(), gc) | |
50 }) | |
51 if err == nil { | |
52 err = innerErr | |
53 } | |
54 return err | |
55 } | |
56 | |
57 func (d *datastoreImpl) GetAll(q Query, dst interface{}) error { | |
58 v := reflect.ValueOf(dst) | |
59 if v.Kind() != reflect.Ptr { | |
60 return fmt.Errorf("invalid GetAll dst: must have a ptr-to-slice: %T", dst) | |
61 } | |
62 if !v.IsValid() || v.IsNil() { | |
63 return errors.New("invalid GetAll dst: <nil>") | |
64 } | |
65 | |
66 if keys, ok := dst.(*[]Key); ok { | |
67 return d.RawInterface.Run(q.KeysOnly(), func(k Key, _ PropertyMa p, _ func() (Cursor, error)) bool { | |
68 *keys = append(*keys, k) | |
69 return true | |
70 }) | |
71 } | |
72 | |
73 slice := v.Elem() | |
74 mat := parseMultiArg(slice.Type()) | |
75 if !mat.valid || mat.newElem == nil { | |
76 return fmt.Errorf("invalid GetAll input type: %T", dst) | |
77 } | |
78 | |
79 lme := errors.LazyMultiError{Size: slice.Len()} | |
80 i := 0 | |
81 err := d.RawInterface.Run(q, func(k Key, pm PropertyMap, _ func() (Curso r, error)) bool { | |
82 slice.Set(reflect.Append(slice, mat.newElem())) | |
83 itm := slice.Index(i) | |
84 mat.setKey(itm, k) | |
85 lme.Assign(i, mat.setPM(itm, pm)) | |
86 i++ | |
87 return true | |
88 }) | |
89 if err == nil { | |
90 err = lme.Get() | |
91 } | |
92 return err | |
93 } | |
94 | |
95 func isOkType(v reflect.Type) bool { | |
96 if v.Implements(typeOfPropertyLoadSaver) { | |
97 return true | |
98 } | |
99 if v.Kind() == reflect.Ptr && v.Elem().Kind() == reflect.Struct { | |
100 return true | |
101 } | |
102 return false | |
103 } | |
104 | |
105 func (d *datastoreImpl) Get(dst interface{}) (err error) { | |
106 if !isOkType(reflect.TypeOf(dst)) { | |
107 return fmt.Errorf("invalid Get input type: %T", dst) | |
108 } | |
109 return errors.SingleError(d.GetMulti([]interface{}{dst})) | |
110 } | |
111 | |
112 func (d *datastoreImpl) Put(src interface{}) (err error) { | |
113 if !isOkType(reflect.TypeOf(src)) { | |
Vadim Sh.
2015/08/03 21:25:12
so Put requires passing values by pointer? Does it
iannucci
2015/08/03 21:51:48
Yeah, it requires pass by pointer. It COULD make s
| |
114 return fmt.Errorf("invalid Put input type: %T", src) | |
115 } | |
116 return errors.SingleError(d.PutMulti([]interface{}{src})) | |
117 } | |
118 | |
119 func (d *datastoreImpl) Delete(key Key) (err error) { | |
120 return errors.SingleError(d.DeleteMulti([]Key{key})) | |
121 } | |
122 | |
123 func (d *datastoreImpl) GetMulti(dst interface{}) error { | |
124 slice := reflect.ValueOf(dst) | |
125 mat := parseMultiArg(slice.Type()) | |
126 if !mat.valid { | |
127 return fmt.Errorf("invalid GetMulti input type: %T", dst) | |
128 } | |
129 | |
130 keys, err := mat.GetKeys(d.NewKey, slice) | |
131 if err != nil { | |
132 return err | |
133 } | |
134 | |
135 lme := errors.LazyMultiError{Size: len(keys)} | |
136 i := 0 | |
137 err = d.RawInterface.GetMulti(keys, func(pm PropertyMap, err error) { | |
138 if !lme.Assign(i, err) { | |
139 lme.Assign(i, mat.setPM(slice.Index(i), pm)) | |
140 } | |
141 i++ | |
142 }) | |
143 | |
144 if err == nil { | |
145 err = lme.Get() | |
146 } | |
147 return err | |
148 } | |
149 | |
150 func (d *datastoreImpl) PutMulti(src interface{}) error { | |
151 slice := reflect.ValueOf(src) | |
152 mat := parseMultiArg(slice.Type()) | |
153 if !mat.valid { | |
154 return fmt.Errorf("invalid PutMulti input type: %T", src) | |
155 } | |
156 | |
157 keys, err := mat.GetKeys(d.NewKey, slice) | |
158 if err != nil { | |
159 return err | |
160 } | |
161 | |
162 vals, err := mat.GetPMs(slice) | |
163 if err != nil { | |
164 return err | |
165 } | |
166 | |
167 lme := errors.LazyMultiError{Size: len(keys)} | |
168 i := 0 | |
169 err = d.RawInterface.PutMulti(keys, vals, func(key Key, err error) { | |
170 if key != keys[i] { | |
171 mat.setKey(slice.Index(i), key) | |
172 } | |
173 lme.Assign(i, err) | |
174 i++ | |
175 }) | |
176 | |
177 if err == nil { | |
178 err = lme.Get() | |
179 } | |
180 return err | |
181 } | |
182 | |
183 func (d *datastoreImpl) DeleteMulti(keys []Key) (err error) { | |
184 lme := errors.LazyMultiError{Size: len(keys)} | |
185 i := 0 | |
186 extErr := d.RawInterface.DeleteMulti(keys, func(internalErr error) { | |
187 lme.Assign(i, internalErr) | |
188 i++ | |
189 }) | |
190 err = lme.Get() | |
191 if err == nil { | |
192 err = extErr | |
193 } | |
194 return | |
195 } | |
196 | |
197 func (d *datastoreImpl) Raw() RawInterface { | |
198 return d.RawInterface | |
199 } | |
OLD | NEW |