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 » "github.com/luci/luci-go/common/errors" |
| 10 » "golang.org/x/net/context" |
| 11 » "google.golang.org/appengine" |
10 "google.golang.org/appengine/datastore" | 12 "google.golang.org/appengine/datastore" |
11 ) | 13 ) |
12 | 14 |
13 type dsKeyImpl struct { | 15 type dsKeyImpl struct { |
14 *datastore.Key | 16 *datastore.Key |
15 } | 17 } |
16 | 18 |
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 | 19 // dsR2F (DS real-to-fake) converts an SDK Key to a ds.Key |
29 func dsR2F(k *datastore.Key) ds.Key { | 20 func dsR2F(k *datastore.Key) *ds.Key { |
30 if k == nil { | 21 if k == nil { |
31 return nil | 22 return nil |
32 } | 23 } |
33 » return dsKeyImpl{k} | 24 » aid := k.AppID() |
| 25 » ns := k.Namespace() |
| 26 |
| 27 » count := 0 |
| 28 » for nk := k; nk != nil; nk = nk.Parent() { |
| 29 » » count++ |
| 30 » } |
| 31 |
| 32 » toks := make([]ds.KeyTok, count) |
| 33 |
| 34 » for ; k != nil; k = k.Parent() { |
| 35 » » count-- |
| 36 » » toks[count].Kind = k.Kind() |
| 37 » » toks[count].StringID = k.StringID() |
| 38 » » toks[count].IntID = k.IntID() |
| 39 » } |
| 40 » return ds.NewKeyToks(aid, ns, toks) |
34 } | 41 } |
35 | 42 |
36 // dsF2R (DS fake-to-real) converts a DSKey back to an SDK *Key. | 43 // dsF2R (DS fake-to-real) converts a DSKey back to an SDK *Key. |
37 func dsF2R(k ds.Key) *datastore.Key { | 44 func dsF2R(ctx context.Context, k *ds.Key) (*datastore.Key, error) { |
38 if k == nil { | 45 if k == nil { |
39 » » return nil | 46 » » return nil, nil |
40 } | 47 } |
41 » if rkey, ok := k.(dsKeyImpl); ok { | 48 |
42 » » return rkey.Key | 49 » // drop aid. |
| 50 » _, ns, toks := k.Split() |
| 51 » err := error(nil) |
| 52 » ctx, err = appengine.Namespace(ctx, ns) |
| 53 » if err != nil { |
| 54 » » return nil, err |
43 } | 55 } |
44 » // we should always hit the fast case above, but just in case, safely ro
und | 56 |
45 » // trip through the proto encoding. | 57 » ret := datastore.NewKey(ctx, toks[0].Kind, toks[0].StringID, toks[0].Int
ID, nil) |
46 » rkey, err := datastore.DecodeKey(dskey.Encode(k)) | 58 » for _, t := range toks[1:] { |
47 » if err != nil { | 59 » » 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 } | 60 } |
54 » return rkey | 61 |
| 62 » return ret, nil |
55 } | 63 } |
56 | 64 |
57 // dsMF2R (DS multi-fake-to-fake) converts a slice of wrapped keys to SDK keys. | 65 // dsMF2R (DS multi-fake-to-fake) converts a slice of wrapped keys to SDK keys. |
58 func dsMF2R(ks []ds.Key) []*datastore.Key { | 66 func dsMF2R(ctx context.Context, ks []*ds.Key) ([]*datastore.Key, error) { |
| 67 » lme := errors.NewLazyMultiError(len(ks)) |
59 ret := make([]*datastore.Key, len(ks)) | 68 ret := make([]*datastore.Key, len(ks)) |
| 69 err := error(nil) |
60 for i, k := range ks { | 70 for i, k := range ks { |
61 » » ret[i] = dsF2R(k) | 71 » » ret[i], err = dsF2R(ctx, k) |
| 72 » » lme.Assign(i, err) |
62 } | 73 } |
63 » return ret | 74 » return ret, lme.Get() |
64 } | 75 } |
OLD | NEW |