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 |