github.com/aaabigfish/gopkg@v1.1.0/cloud/metainfo/backward.go (about) 1 // Copyright 2021 ByteDance Inc. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 package metainfo 16 17 import ( 18 "context" 19 "sync" 20 ) 21 22 type bwCtxKeyType int 23 24 const ( 25 bwCtxKeySend bwCtxKeyType = iota 26 bwCtxKeyRecv 27 ) 28 29 type bwCtxValue struct { 30 sync.RWMutex 31 kvs map[string]string 32 } 33 34 func newBackwardCtxValues() *bwCtxValue { 35 return &bwCtxValue{ 36 kvs: make(map[string]string), 37 } 38 } 39 40 func (p *bwCtxValue) get(k string) (v string, ok bool) { 41 p.RLock() 42 v, ok = p.kvs[k] 43 p.RUnlock() 44 return 45 } 46 47 func (p *bwCtxValue) getAll() (m map[string]string) { 48 p.RLock() 49 if cnt := len(p.kvs); cnt > 0 { 50 m = make(map[string]string, cnt) 51 for k, v := range p.kvs { 52 m[k] = v 53 } 54 } 55 p.RUnlock() 56 return 57 } 58 59 func (p *bwCtxValue) set(k, v string) { 60 p.Lock() 61 p.kvs[k] = v 62 p.Unlock() 63 } 64 65 func (p *bwCtxValue) setMany(kvs []string) { 66 p.Lock() 67 for i := 0; i < len(kvs); i += 2 { 68 p.kvs[kvs[i]] = kvs[i+1] 69 } 70 p.Unlock() 71 } 72 73 func (p *bwCtxValue) setMap(kvs map[string]string) { 74 p.Lock() 75 for k, v := range kvs { 76 p.kvs[k] = v 77 } 78 p.Unlock() 79 } 80 81 // WithBackwardValues returns a new context that allows passing key-value pairs 82 // backward with `SetBackwardValue` from any derived context. 83 func WithBackwardValues(ctx context.Context) context.Context { 84 if _, ok := ctx.Value(bwCtxKeyRecv).(*bwCtxValue); ok { 85 return ctx 86 } 87 ctx = context.WithValue(ctx, bwCtxKeyRecv, newBackwardCtxValues()) 88 return ctx 89 } 90 91 // RecvBackwardValue gets a value associated with the given key that is set by 92 // `SetBackwardValue` or `SetBackwardValues`. 93 func RecvBackwardValue(ctx context.Context, key string) (val string, ok bool) { 94 if p, exist := ctx.Value(bwCtxKeyRecv).(*bwCtxValue); exist { 95 val, ok = p.get(key) 96 } 97 return 98 } 99 100 // RecvAllBackwardValues is the batched version of RecvBackwardValue. 101 func RecvAllBackwardValues(ctx context.Context) (m map[string]string) { 102 if p, ok := ctx.Value(bwCtxKeyRecv).(*bwCtxValue); ok { 103 return p.getAll() 104 } 105 return 106 } 107 108 // SetBackwardValue sets a key value pair into the context. 109 func SetBackwardValue(ctx context.Context, key, val string) (ok bool) { 110 if p, ok := ctx.Value(bwCtxKeyRecv).(*bwCtxValue); ok { 111 p.set(key, val) 112 return true 113 } 114 return false 115 } 116 117 // SetBackwardValues is the batched version of `SetBackwardValue`. 118 func SetBackwardValues(ctx context.Context, kvs ...string) (ok bool) { 119 if l := len(kvs); l > 0 && l%2 == 0 { 120 if p, ok := ctx.Value(bwCtxKeyRecv).(*bwCtxValue); ok { 121 p.setMany(kvs) 122 return true 123 } 124 } 125 return 126 } 127 128 // SetBackwardValuesFromMap is the batched version of `SetBackwardValue`. 129 func SetBackwardValuesFromMap(ctx context.Context, kvs map[string]string) (ok bool) { 130 if l := len(kvs); l > 0 { 131 if p, ok := ctx.Value(bwCtxKeyRecv).(*bwCtxValue); ok { 132 p.setMap(kvs) 133 return true 134 } 135 } 136 return 137 } 138 139 // WithBackwardValuesToSend returns a new context that collects key-value 140 // pairs set with `SendBackwardValue` or `SendBackwardValues` into any 141 // derived context. 142 func WithBackwardValuesToSend(ctx context.Context) context.Context { 143 if _, ok := ctx.Value(bwCtxKeySend).(*bwCtxValue); ok { 144 return ctx 145 } 146 ctx = context.WithValue(ctx, bwCtxKeySend, newBackwardCtxValues()) 147 return ctx 148 } 149 150 // SendBackwardValue sets a key-value pair into the context for sending to 151 // a remote endpoint. 152 // Note that the values can not be retrieved with `RecvBackwardValue` from 153 // the same context. 154 func SendBackwardValue(ctx context.Context, key, val string) (ok bool) { 155 if p, ok := ctx.Value(bwCtxKeySend).(*bwCtxValue); ok { 156 p.set(key, val) 157 return true 158 } 159 return 160 } 161 162 // SendBackwardValues is the batched version of `SendBackwardValue`. 163 func SendBackwardValues(ctx context.Context, kvs ...string) (ok bool) { 164 if l := len(kvs); l > 0 && l%2 == 0 { 165 if p, ok := ctx.Value(bwCtxKeySend).(*bwCtxValue); ok { 166 p.setMany(kvs) 167 return true 168 } 169 } 170 return 171 } 172 173 // SendBackwardValuesFromMap is the batched version of `SendBackwardValue`. 174 func SendBackwardValuesFromMap(ctx context.Context, kvs map[string]string) (ok bool) { 175 if l := len(kvs); l > 0 { 176 if p, ok := ctx.Value(bwCtxKeySend).(*bwCtxValue); ok { 177 p.setMap(kvs) 178 return true 179 } 180 } 181 return 182 } 183 184 // AllBackwardValuesToSend retrieves all key-values pairs set by `SendBackwardValue` 185 // or `SendBackwardValues` from the given context. 186 // This function is designed for frameworks, common developers should not use it. 187 func AllBackwardValuesToSend(ctx context.Context) (m map[string]string) { 188 if p, ok := ctx.Value(bwCtxKeySend).(*bwCtxValue); ok { 189 return p.getAll() 190 } 191 return 192 } 193 194 // GetBackwardValue is an alias to `RecvBackwardValue`. 195 // Deprecated: for clarity, please use `RecvBackwardValue` instead. 196 func GetBackwardValue(ctx context.Context, key string) (val string, ok bool) { 197 return RecvBackwardValue(ctx, key) 198 } 199 200 // GetAllBackwardValues is an alias to RecvAllBackwardValues. 201 // Deprecated: for clarity, please use `RecvAllBackwardValues` instead. 202 func GetAllBackwardValues(ctx context.Context) map[string]string { 203 return RecvAllBackwardValues(ctx) 204 }