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) 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 |