Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1139)

Unified Diff: service/datastore/datastore.go

Issue 2302743002: Interface update, per-method Contexts. (Closed)
Patch Set: Lightning talk licenses. Created 4 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « service/datastore/context_test.go ('k') | service/datastore/datastore_test.go » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: service/datastore/datastore.go
diff --git a/service/datastore/datastore.go b/service/datastore/datastore.go
index 5acacbd02b643a13e22b43d6b81ec856e1836909..99f7f40953a1defdca618db13fc0a3fbad5e752e 100644
--- a/service/datastore/datastore.go
+++ b/service/datastore/datastore.go
@@ -10,542 +10,12 @@ import (
"io/ioutil"
"os"
"path/filepath"
- "reflect"
"runtime"
"strings"
- "github.com/luci/luci-go/common/errors"
-
"gopkg.in/yaml.v2"
)
-type datastoreImpl struct {
- RawInterface
-
- aid string
- ns string
-}
-
-var _ Interface = (*datastoreImpl)(nil)
-
-func (d *datastoreImpl) KeyForObj(src interface{}) *Key {
- ret, err := d.KeyForObjErr(src)
- if err != nil {
- panic(err)
- }
- return ret
-}
-
-func (d *datastoreImpl) KeyForObjErr(src interface{}) (*Key, error) {
- return newKeyObjErr(d.aid, d.ns, getMGS(src))
-}
-
-func (d *datastoreImpl) MakeKey(elems ...interface{}) *Key {
- return MakeKey(d.aid, d.ns, elems...)
-}
-
-func (d *datastoreImpl) NewKey(kind, stringID string, intID int64, parent *Key) *Key {
- return NewKey(d.aid, d.ns, kind, stringID, intID, parent)
-}
-
-func (d *datastoreImpl) NewIncompleteKeys(count int, kind string, parent *Key) (keys []*Key) {
- if count > 0 {
- keys = make([]*Key, count)
- for i := range keys {
- keys[i] = d.NewKey(kind, "", 0, parent)
- }
- }
- return
-}
-
-func (d *datastoreImpl) NewKeyToks(toks []KeyTok) *Key {
- return NewKeyToks(d.aid, d.ns, toks)
-}
-
-// PopulateKey loads key into obj.
-//
-// obj is any object that Interface.Get is able to accept.
-//
-// Upon successful application, this method will return true. If the key could
-// not be applied to the object, this method will return false. It will panic if
-// obj is an invalid datastore model.
-//
-// This method will panic if obj is an invalid datastore model. If the key could
-// not be applied to the object, nothing will happen.
-func PopulateKey(obj interface{}, key *Key) bool {
- return populateKeyMGS(getMGS(obj), key)
-}
-
-func populateKeyMGS(mgs MetaGetterSetter, key *Key) bool {
- if mgs.SetMeta("key", key) {
- return true
- }
-
- lst := key.LastTok()
- if lst.StringID != "" {
- if !mgs.SetMeta("id", lst.StringID) {
- return false
- }
- } else {
- if !mgs.SetMeta("id", lst.IntID) {
- return false
- }
- }
-
- mgs.SetMeta("kind", lst.Kind)
- mgs.SetMeta("parent", key.Parent())
- return true
-}
-
-func checkMultiSliceType(v interface{}) error {
- if reflect.TypeOf(v).Kind() == reflect.Slice {
- return nil
- }
- return fmt.Errorf("argument must be a slice, not %T", v)
-
-}
-
-func runParseCallback(cbIface interface{}) (isKey, hasErr, hasCursorCB bool, mat *multiArgType) {
- badSig := func() {
- panic(fmt.Errorf(
- "cb does not match the required callback signature: `%T` != `func(TYPE, [CursorCB]) [error]`",
- cbIface))
- }
-
- if cbIface == nil {
- badSig()
- }
-
- // TODO(riannucci): Profile and determine if any of this is causing a real
- // slowdown. Could potentially cache reflection stuff by cbTyp?
- cbTyp := reflect.TypeOf(cbIface)
-
- if cbTyp.Kind() != reflect.Func {
- badSig()
- }
-
- numIn := cbTyp.NumIn()
- if numIn != 1 && numIn != 2 {
- badSig()
- }
-
- firstArg := cbTyp.In(0)
- if firstArg == typeOfKey {
- isKey = true
- } else {
- mat = mustParseArg(firstArg, false)
- if mat.newElem == nil {
- badSig()
- }
- }
-
- hasCursorCB = numIn == 2
- if hasCursorCB && cbTyp.In(1) != typeOfCursorCB {
- badSig()
- }
-
- if cbTyp.NumOut() > 1 {
- badSig()
- } else if cbTyp.NumOut() == 1 && cbTyp.Out(0) != typeOfError {
- badSig()
- }
- hasErr = cbTyp.NumOut() == 1
-
- return
-}
-
-func (d *datastoreImpl) AllocateIDs(ent ...interface{}) error {
- if len(ent) == 0 {
- return nil
- }
-
- mma, err := makeMetaMultiArg(ent, mmaWriteKeys)
- if err != nil {
- panic(err)
- }
-
- keys, _, err := mma.getKeysPMs(d.aid, d.ns, false)
- if err != nil {
- if len(ent) == 1 {
- // Single-argument Exists will return a single error.
- err = errors.SingleError(err)
- }
- return err
- }
- if len(keys) == 0 {
- return nil
- }
-
- // Convert each key to be partial valid, assigning an integer ID of 0. Confirm
- // that each object can be populated with such a key.
- for i, key := range keys {
- keys[i] = key.Incomplete()
- }
-
- var et errorTracker
- it := mma.iterator(et.init(mma))
- err = filterStop(d.RawInterface.AllocateIDs(keys, func(key *Key, err error) error {
- it.next(func(mat *multiArgType, v reflect.Value) error {
- if err != nil {
- return err
- }
-
- if !mat.setKey(v, key) {
- return ErrInvalidKey
- }
- return nil
- })
-
- return nil
- }))
- if err == nil {
- err = et.error()
- }
-
- if err != nil && len(ent) == 1 {
- // Single-argument Exists will return a single error.
- err = errors.SingleError(err)
- }
- return err
-}
-
-func (d *datastoreImpl) Run(q *Query, cbIface interface{}) error {
- isKey, hasErr, hasCursorCB, mat := runParseCallback(cbIface)
-
- if isKey {
- q = q.KeysOnly(true)
- }
- fq, err := q.Finalize()
- if err != nil {
- return err
- }
-
- cbVal := reflect.ValueOf(cbIface)
- var cb func(reflect.Value, CursorCB) error
- switch {
- case hasErr && hasCursorCB:
- cb = func(v reflect.Value, cb CursorCB) error {
- err := cbVal.Call([]reflect.Value{v, reflect.ValueOf(cb)})[0].Interface()
- if err != nil {
- return err.(error)
- }
- return nil
- }
-
- case hasErr && !hasCursorCB:
- cb = func(v reflect.Value, _ CursorCB) error {
- err := cbVal.Call([]reflect.Value{v})[0].Interface()
- if err != nil {
- return err.(error)
- }
- return nil
- }
-
- case !hasErr && hasCursorCB:
- cb = func(v reflect.Value, cb CursorCB) error {
- cbVal.Call([]reflect.Value{v, reflect.ValueOf(cb)})
- return nil
- }
-
- case !hasErr && !hasCursorCB:
- cb = func(v reflect.Value, _ CursorCB) error {
- cbVal.Call([]reflect.Value{v})
- return nil
- }
- }
-
- if isKey {
- err = d.RawInterface.Run(fq, func(k *Key, _ PropertyMap, gc CursorCB) error {
- return cb(reflect.ValueOf(k), gc)
- })
- } else {
- err = d.RawInterface.Run(fq, func(k *Key, pm PropertyMap, gc CursorCB) error {
- itm := mat.newElem()
- if err := mat.setPM(itm, pm); err != nil {
- return err
- }
- mat.setKey(itm, k)
- return cb(itm, gc)
- })
- }
- return filterStop(err)
-}
-
-func (d *datastoreImpl) Count(q *Query) (int64, error) {
- fq, err := q.Finalize()
- if err != nil {
- return 0, err
- }
- v, err := d.RawInterface.Count(fq)
- return v, filterStop(err)
-}
-
-func (d *datastoreImpl) GetAll(q *Query, dst interface{}) error {
- v := reflect.ValueOf(dst)
- if v.Kind() != reflect.Ptr {
- panic(fmt.Errorf("invalid GetAll dst: must have a ptr-to-slice: %T", dst))
- }
- if !v.IsValid() || v.IsNil() {
- panic(errors.New("invalid GetAll dst: <nil>"))
- }
-
- if keys, ok := dst.(*[]*Key); ok {
- fq, err := q.KeysOnly(true).Finalize()
- if err != nil {
- return err
- }
-
- return d.RawInterface.Run(fq, func(k *Key, _ PropertyMap, _ CursorCB) error {
- *keys = append(*keys, k)
- return nil
- })
- }
- fq, err := q.Finalize()
- if err != nil {
- return err
- }
-
- slice := v.Elem()
- mat := mustParseMultiArg(slice.Type())
- if mat.newElem == nil {
- panic(fmt.Errorf("invalid GetAll dst (non-concrete element type): %T", dst))
- }
-
- errs := map[int]error{}
- i := 0
- err = filterStop(d.RawInterface.Run(fq, func(k *Key, pm PropertyMap, _ CursorCB) error {
- slice.Set(reflect.Append(slice, mat.newElem()))
- itm := slice.Index(i)
- mat.setKey(itm, k)
- err := mat.setPM(itm, pm)
- if err != nil {
- errs[i] = err
- }
- i++
- return nil
- }))
- if err == nil {
- if len(errs) > 0 {
- me := make(errors.MultiError, slice.Len())
- for i, e := range errs {
- me[i] = e
- }
- err = me
- }
- }
- return err
-}
-
-func (d *datastoreImpl) Exists(ent ...interface{}) (*ExistsResult, error) {
- if len(ent) == 0 {
- return nil, nil
- }
-
- mma, err := makeMetaMultiArg(ent, mmaKeysOnly)
- if err != nil {
- panic(err)
- }
-
- keys, _, err := mma.getKeysPMs(d.aid, d.ns, false)
- if err != nil {
- if len(ent) == 1 {
- // Single-argument Exists will return a single error.
- err = errors.SingleError(err)
- }
- return nil, err
- }
- if len(keys) == 0 {
- return nil, nil
- }
-
- var bt boolTracker
- it := mma.iterator(bt.init(mma))
- err = filterStop(d.RawInterface.GetMulti(keys, nil, func(_ PropertyMap, err error) error {
- it.next(func(*multiArgType, reflect.Value) error {
- return err
- })
- return nil
- }))
- if err == nil {
- err = bt.error()
- }
-
- if err != nil && len(ent) == 1 {
- // Single-argument Exists will return a single error.
- err = errors.SingleError(err)
- }
- return bt.result(), err
-}
-
-func (d *datastoreImpl) ExistsMulti(keys []*Key) (BoolList, error) {
- v, err := d.Exists(keys)
- if err != nil {
- return nil, err
- }
- return v.List(0), nil
-}
-
-func (d *datastoreImpl) Get(dst ...interface{}) (err error) {
- if len(dst) == 0 {
- return nil
- }
-
- mma, err := makeMetaMultiArg(dst, mmaReadWrite)
- if err != nil {
- panic(err)
- }
-
- keys, pms, err := mma.getKeysPMs(d.aid, d.ns, true)
- if err != nil {
- if len(dst) == 1 {
- // Single-argument Get will return a single error.
- err = errors.SingleError(err)
- }
- return err
- }
- if len(keys) == 0 {
- return nil
- }
-
- var et errorTracker
- it := mma.iterator(et.init(mma))
- meta := NewMultiMetaGetter(pms)
- err = filterStop(d.RawInterface.GetMulti(keys, meta, func(pm PropertyMap, err error) error {
- it.next(func(mat *multiArgType, slot reflect.Value) error {
- if err != nil {
- return err
- }
- return mat.setPM(slot, pm)
- })
- return nil
- }))
-
- if err == nil {
- err = et.error()
- }
-
- if err != nil && len(dst) == 1 {
- // Single-argument Get will return a single error.
- err = errors.SingleError(err)
- }
- return err
-}
-
-func (d *datastoreImpl) GetMulti(dst interface{}) error {
- if err := checkMultiSliceType(dst); err != nil {
- panic(err)
- }
- return d.Get(dst)
-}
-
-func (d *datastoreImpl) Put(src ...interface{}) (err error) {
- if len(src) == 0 {
- return nil
- }
-
- mma, err := makeMetaMultiArg(src, mmaReadWrite)
- if err != nil {
- panic(err)
- }
-
- keys, vals, err := mma.getKeysPMs(d.aid, d.ns, false)
- if err != nil {
- if len(src) == 1 {
- // Single-argument Put will return a single error.
- err = errors.SingleError(err)
- }
- return err
- }
- if len(keys) == 0 {
- return nil
- }
-
- i := 0
- var et errorTracker
- it := mma.iterator(et.init(mma))
- err = filterStop(d.RawInterface.PutMulti(keys, vals, func(key *Key, err error) error {
- it.next(func(mat *multiArgType, slot reflect.Value) error {
- if err != nil {
- return err
- }
- if key != keys[i] {
- mat.setKey(slot, key)
- }
- return nil
- })
-
- i++
- return nil
- }))
-
- if err == nil {
- err = et.error()
- }
-
- if err != nil && len(src) == 1 {
- // Single-argument Put will return a single error.
- err = errors.SingleError(err)
- }
- return err
-}
-
-func (d *datastoreImpl) PutMulti(src interface{}) error {
- if err := checkMultiSliceType(src); err != nil {
- panic(err)
- }
- return d.Put(src)
-}
-
-func (d *datastoreImpl) Delete(ent ...interface{}) error {
- if len(ent) == 0 {
- return nil
- }
-
- mma, err := makeMetaMultiArg(ent, mmaKeysOnly)
- if err != nil {
- panic(err)
- }
-
- keys, _, err := mma.getKeysPMs(d.aid, d.ns, false)
- if err != nil {
- if len(ent) == 1 {
- // Single-argument Delete will return a single error.
- err = errors.SingleError(err)
- }
- return err
- }
- if len(keys) == 0 {
- return nil
- }
-
- var et errorTracker
- it := mma.iterator(et.init(mma))
- err = filterStop(d.RawInterface.DeleteMulti(keys, func(err error) error {
- it.next(func(*multiArgType, reflect.Value) error {
- return err
- })
-
- return nil
- }))
- if err == nil {
- err = et.error()
- }
-
- if err != nil && len(ent) == 1 {
- // Single-argument Delete will return a single error.
- err = errors.SingleError(err)
- }
- return err
-}
-
-func (d *datastoreImpl) DeleteMulti(keys []*Key) error {
- return d.Delete(keys)
-}
-
-func (d *datastoreImpl) Raw() RawInterface {
- return d.RawInterface
-}
-
// ParseIndexYAML parses the contents of a index YAML file into a list of
// IndexDefinitions.
func ParseIndexYAML(content io.Reader) ([]*IndexDefinition, error) {
@@ -628,10 +98,3 @@ func FindAndParseIndexYAML(path string) ([]*IndexDefinition, error) {
currentDir = filepath.Dir(currentDir)
}
}
-
-func filterStop(err error) error {
- if err == Stop {
- err = nil
- }
- return err
-}
« no previous file with comments | « service/datastore/context_test.go ('k') | service/datastore/datastore_test.go » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698