| 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 datastore | 5 package datastore |
| 6 | 6 |
| 7 import ( | 7 import ( |
| 8 "github.com/luci/gae/service/info" | 8 "github.com/luci/gae/service/info" |
| 9 "golang.org/x/net/context" | 9 "golang.org/x/net/context" |
| 10 ) | 10 ) |
| 11 | 11 |
| 12 type key int | 12 type key int |
| 13 | 13 |
| 14 var ( | 14 var ( |
| 15 rawDatastoreKey key | 15 rawDatastoreKey key |
| 16 rawDatastoreFilterKey key = 1 | 16 rawDatastoreFilterKey key = 1 |
| 17 ) | 17 ) |
| 18 | 18 |
| 19 // RawFactory is the function signature for factory methods compatible with | 19 // RawFactory is the function signature for factory methods compatible with |
| 20 // SetRawFactory. | 20 // SetRawFactory. wantTxn is true if the Factory should return the datastore in |
| 21 type RawFactory func(context.Context) RawInterface | 21 // the current transaction, and false if the Factory should return the |
| 22 // non-transactional (root) datastore. |
| 23 type RawFactory func(c context.Context, wantTxn bool) RawInterface |
| 22 | 24 |
| 23 // RawFilter is the function signature for a RawFilter implementation. It | 25 // RawFilter is the function signature for a RawFilter implementation. It |
| 24 // gets the current RDS implementation, and returns a new RDS implementation | 26 // gets the current RDS implementation, and returns a new RDS implementation |
| 25 // backed by the one passed in. | 27 // backed by the one passed in. |
| 26 type RawFilter func(context.Context, RawInterface) RawInterface | 28 type RawFilter func(context.Context, RawInterface) RawInterface |
| 27 | 29 |
| 28 // getUnfiltered gets gets the RawInterface implementation from context without | 30 // getUnfiltered gets gets the RawInterface implementation from context without |
| 29 // any of the filters applied. | 31 // any of the filters applied. |
| 30 func getUnfiltered(c context.Context) RawInterface { | 32 func getUnfiltered(c context.Context, wantTxn bool) RawInterface { |
| 31 if f, ok := c.Value(rawDatastoreKey).(RawFactory); ok && f != nil { | 33 if f, ok := c.Value(rawDatastoreKey).(RawFactory); ok && f != nil { |
| 32 » » return f(c) | 34 » » return f(c, wantTxn) |
| 33 } | 35 } |
| 34 return nil | 36 return nil |
| 35 } | 37 } |
| 36 | 38 |
| 37 // GetRaw gets the RawInterface implementation from context. | 39 // getFiltered gets the datastore (transactional or not), and applies all of |
| 38 func GetRaw(c context.Context) RawInterface { | 40 // the currently installed filters to it. |
| 39 » ret := getUnfiltered(c) | 41 func getFiltered(c context.Context, wantTxn bool) RawInterface { |
| 42 » ret := getUnfiltered(c, wantTxn) |
| 40 if ret == nil { | 43 if ret == nil { |
| 41 return nil | 44 return nil |
| 42 } | 45 } |
| 43 for _, f := range getCurFilters(c) { | 46 for _, f := range getCurFilters(c) { |
| 44 ret = f(c, ret) | 47 ret = f(c, ret) |
| 45 } | 48 } |
| 46 return applyCheckFilter(c, ret) | 49 return applyCheckFilter(c, ret) |
| 47 } | 50 } |
| 48 | 51 |
| 52 // GetRaw gets the RawInterface implementation from context. |
| 53 func GetRaw(c context.Context) RawInterface { |
| 54 return getFiltered(c, true) |
| 55 } |
| 56 |
| 57 // GetRawNoTxn gets the RawInterface implementation from context. If there's a |
| 58 // currently active transaction, this will return a non-transactional connection |
| 59 // to the datastore, otherwise this is the same as GetRaw. |
| 60 func GetRawNoTxn(c context.Context) RawInterface { |
| 61 return getFiltered(c, false) |
| 62 } |
| 63 |
| 49 // Get gets the Interface implementation from context. | 64 // Get gets the Interface implementation from context. |
| 50 func Get(c context.Context) Interface { | 65 func Get(c context.Context) Interface { |
| 51 inf := info.Get(c) | 66 inf := info.Get(c) |
| 52 return &datastoreImpl{ | 67 return &datastoreImpl{ |
| 53 GetRaw(c), | 68 GetRaw(c), |
| 54 inf.FullyQualifiedAppID(), | 69 inf.FullyQualifiedAppID(), |
| 55 inf.GetNamespace(), | 70 inf.GetNamespace(), |
| 56 } | 71 } |
| 57 } | 72 } |
| 58 | 73 |
| 74 // GetNoTxn gets the Interface implementation from context. If there's a |
| 75 // currently active transaction, this will return a non-transactional connection |
| 76 // to the datastore, otherwise this is the same as GetRaw. |
| 77 // Get gets the Interface implementation from context. |
| 78 func GetNoTxn(c context.Context) Interface { |
| 79 inf := info.Get(c) |
| 80 return &datastoreImpl{ |
| 81 GetRawNoTxn(c), |
| 82 inf.FullyQualifiedAppID(), |
| 83 inf.GetNamespace(), |
| 84 } |
| 85 } |
| 86 |
| 59 // SetRawFactory sets the function to produce Datastore instances, as returned b
y | 87 // SetRawFactory sets the function to produce Datastore instances, as returned b
y |
| 60 // the GetRaw method. | 88 // the GetRaw method. |
| 61 func SetRawFactory(c context.Context, rdsf RawFactory) context.Context { | 89 func SetRawFactory(c context.Context, rdsf RawFactory) context.Context { |
| 62 return context.WithValue(c, rawDatastoreKey, rdsf) | 90 return context.WithValue(c, rawDatastoreKey, rdsf) |
| 63 } | 91 } |
| 64 | 92 |
| 65 // SetRaw sets the current Datastore object in the context. Useful for testing | 93 // SetRaw sets the current Datastore object in the context. Useful for testing |
| 66 // with a quick mock. This is just a shorthand SetRawFactory invocation to set | 94 // with a quick mock. This is just a shorthand SetRawFactory invocation to set |
| 67 // a factory which always returns the same object. | 95 // a factory which always returns the same object. |
| 68 func SetRaw(c context.Context, rds RawInterface) context.Context { | 96 func SetRaw(c context.Context, rds RawInterface) context.Context { |
| 69 » return SetRawFactory(c, func(context.Context) RawInterface { return rds
}) | 97 » return SetRawFactory(c, func(context.Context, bool) RawInterface { retur
n rds }) |
| 70 } | 98 } |
| 71 | 99 |
| 72 func getCurFilters(c context.Context) []RawFilter { | 100 func getCurFilters(c context.Context) []RawFilter { |
| 73 curFiltsI := c.Value(rawDatastoreFilterKey) | 101 curFiltsI := c.Value(rawDatastoreFilterKey) |
| 74 if curFiltsI != nil { | 102 if curFiltsI != nil { |
| 75 return curFiltsI.([]RawFilter) | 103 return curFiltsI.([]RawFilter) |
| 76 } | 104 } |
| 77 return nil | 105 return nil |
| 78 } | 106 } |
| 79 | 107 |
| 80 // AddRawFilters adds RawInterface filters to the context. | 108 // AddRawFilters adds RawInterface filters to the context. |
| 81 func AddRawFilters(c context.Context, filts ...RawFilter) context.Context { | 109 func AddRawFilters(c context.Context, filts ...RawFilter) context.Context { |
| 82 if len(filts) == 0 { | 110 if len(filts) == 0 { |
| 83 return c | 111 return c |
| 84 } | 112 } |
| 85 cur := getCurFilters(c) | 113 cur := getCurFilters(c) |
| 86 newFilts := make([]RawFilter, 0, len(cur)+len(filts)) | 114 newFilts := make([]RawFilter, 0, len(cur)+len(filts)) |
| 87 newFilts = append(newFilts, getCurFilters(c)...) | 115 newFilts = append(newFilts, getCurFilters(c)...) |
| 88 newFilts = append(newFilts, filts...) | 116 newFilts = append(newFilts, filts...) |
| 89 return context.WithValue(c, rawDatastoreFilterKey, newFilts) | 117 return context.WithValue(c, rawDatastoreFilterKey, newFilts) |
| 90 } | 118 } |
| OLD | NEW |