github.com/bytedance/gopkg@v0.0.0-20240514070511-01b2cbcf35e1/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  // GetBackwardValueToSend gets a value associated with the given key that is set by
   185  // `SendBackwardValue`, `SendBackwardValues` or `SendBackwardValuesFromMap`.
   186  func GetBackwardValueToSend(ctx context.Context, key string) (val string, ok bool) {
   187  	if p, exist := ctx.Value(bwCtxKeySend).(*bwCtxValue); exist {
   188  		val, ok = p.get(key)
   189  	}
   190  	return
   191  }
   192  
   193  // AllBackwardValuesToSend retrieves all key-values pairs set by `SendBackwardValue`
   194  // or `SendBackwardValues` from the given context.
   195  // This function is designed for frameworks, common developers should not use it.
   196  func AllBackwardValuesToSend(ctx context.Context) (m map[string]string) {
   197  	if p, ok := ctx.Value(bwCtxKeySend).(*bwCtxValue); ok {
   198  		return p.getAll()
   199  	}
   200  	return
   201  }
   202  
   203  // GetBackwardValue is an alias to `RecvBackwardValue`.
   204  // Deprecated: for clarity, please use `RecvBackwardValue` instead.
   205  func GetBackwardValue(ctx context.Context, key string) (val string, ok bool) {
   206  	return RecvBackwardValue(ctx, key)
   207  }
   208  
   209  // GetAllBackwardValues is an alias to RecvAllBackwardValues.
   210  // Deprecated: for clarity, please use `RecvAllBackwardValues` instead.
   211  func GetAllBackwardValues(ctx context.Context) map[string]string {
   212  	return RecvAllBackwardValues(ctx)
   213  }