Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2015 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 package prod | 5 package prod |
| 6 | 6 |
| 7 import ( | 7 import ( |
| 8 ds "github.com/luci/gae/service/datastore" | 8 ds "github.com/luci/gae/service/datastore" |
| 9 » "github.com/luci/gae/service/datastore/dskey" | 9 » "golang.org/x/net/context" |
| 10 » "google.golang.org/appengine" | |
| 10 "google.golang.org/appengine/datastore" | 11 "google.golang.org/appengine/datastore" |
| 11 ) | 12 ) |
| 12 | 13 |
| 13 type dsKeyImpl struct { | 14 type dsKeyImpl struct { |
| 14 *datastore.Key | 15 *datastore.Key |
| 15 } | 16 } |
| 16 | 17 |
| 17 var _ ds.Key = dsKeyImpl{} | |
| 18 | |
| 19 func (k dsKeyImpl) Parent() ds.Key { return dsR2F(k.Key.Parent()) } | |
| 20 func (k dsKeyImpl) Incomplete() bool { return k.Key.Incomplete() } | |
| 21 func (k dsKeyImpl) Valid(allowSpecial bool, aid, ns string) bool { | |
| 22 return dskey.Valid(k, allowSpecial, aid, ns) | |
| 23 } | |
| 24 func (k dsKeyImpl) PartialValid(aid, ns string) bool { | |
| 25 return dskey.PartialValid(k, aid, ns) | |
| 26 } | |
| 27 | |
| 28 // dsR2F (DS real-to-fake) converts an SDK Key to a ds.Key | 18 // dsR2F (DS real-to-fake) converts an SDK Key to a ds.Key |
| 29 func dsR2F(k *datastore.Key) ds.Key { | 19 func dsR2F(k *datastore.Key) *ds.Key { |
| 30 if k == nil { | 20 if k == nil { |
| 31 return nil | 21 return nil |
| 32 } | 22 } |
| 33 » return dsKeyImpl{k} | 23 » aid := k.AppID() |
| 24 » ns := k.Namespace() | |
| 25 » toks := []ds.KeyTok(nil) | |
|
dnj
2015/09/18 16:47:57
Since this will be executed frequently, it may be
iannucci
2015/09/18 22:25:48
done
| |
| 26 » for k != nil { | |
| 27 » » toks = append(toks, ds.KeyTok{ | |
| 28 » » » Kind: k.Kind(), StringID: k.StringID(), IntID: k.IntID() }) | |
| 29 » » k = k.Parent() | |
| 30 » } | |
| 31 » for i, j := 0, len(toks)-1; i < j; i, j = i+1, j-1 { | |
| 32 » » toks[i], toks[j] = toks[j], toks[i] | |
| 33 » } | |
| 34 » return ds.NewKeyToks(aid, ns, toks) | |
| 34 } | 35 } |
| 35 | 36 |
| 36 // dsF2R (DS fake-to-real) converts a DSKey back to an SDK *Key. | 37 // dsF2R (DS fake-to-real) converts a DSKey back to an SDK *Key. |
| 37 func dsF2R(k ds.Key) *datastore.Key { | 38 func dsF2R(ctx context.Context, k *ds.Key) (*datastore.Key, error) { |
| 38 if k == nil { | 39 if k == nil { |
| 39 » » return nil | 40 » » return nil, nil |
| 40 } | 41 } |
| 41 » if rkey, ok := k.(dsKeyImpl); ok { | 42 |
| 42 » » return rkey.Key | 43 » // drop aid. |
| 44 » _, ns, toks := k.Split() | |
|
iannucci
2015/09/18 04:31:52
We drop the appid here... we can't actually contro
dnj
2015/09/18 16:47:57
Please document this in a formal comment.
Note th
iannucci
2015/09/18 22:25:48
Noted in doc.go as a BUG.
| |
| 45 » err := error(nil) | |
| 46 » ctx, err = appengine.Namespace(ctx, ns) | |
| 47 » if err != nil { | |
| 48 » » return nil, err | |
| 43 } | 49 } |
| 44 » // we should always hit the fast case above, but just in case, safely ro und | 50 |
| 45 » // trip through the proto encoding. | 51 » ret := datastore.NewKey(ctx, toks[0].Kind, toks[0].StringID, toks[0].Int ID, nil) |
| 46 » rkey, err := datastore.DecodeKey(dskey.Encode(k)) | 52 » for _, t := range toks[1:] { |
| 47 » if err != nil { | 53 » » ret = datastore.NewKey(ctx, t.Kind, t.StringID, t.IntID, ret) |
| 48 » » // should never happen in a good program, but it's not ignorable , and | |
| 49 » » // passing an error back makes this function too cumbersome (and it causes | |
| 50 » » // this `if err != nil { panic(err) }` logic to show up in a bun ch of | |
| 51 » » // places. Realistically, everything should hit the early exit c lause above. | |
| 52 » » panic(err) | |
| 53 } | 54 } |
| 54 » return rkey | 55 |
| 56 » return ret, nil | |
| 55 } | 57 } |
| 56 | 58 |
| 57 // dsMF2R (DS multi-fake-to-fake) converts a slice of wrapped keys to SDK keys. | 59 // dsMF2R (DS multi-fake-to-fake) converts a slice of wrapped keys to SDK keys. |
| 58 func dsMF2R(ks []ds.Key) []*datastore.Key { | 60 func dsMF2R(ctx context.Context, ks []*ds.Key) ([]*datastore.Key, error) { |
| 61 » err := error(nil) | |
|
dnj
2015/09/18 16:47:57
Does it make sense to use a MultiError here?
iannucci
2015/09/18 22:25:47
yuuuup
| |
| 59 ret := make([]*datastore.Key, len(ks)) | 62 ret := make([]*datastore.Key, len(ks)) |
| 60 for i, k := range ks { | 63 for i, k := range ks { |
| 61 » » ret[i] = dsF2R(k) | 64 » » if ret[i], err = dsF2R(ctx, k); err != nil { |
| 65 » » » return nil, err | |
| 66 » » } | |
| 62 } | 67 } |
| 63 » return ret | 68 » return ret, nil |
| 64 } | 69 } |
| OLD | NEW |