Chromium Code Reviews| 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 |