go.etcd.io/etcd@v3.3.27+incompatible/clientv3/namespace/kv.go (about)

     1  // Copyright 2017 The etcd Authors
     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 namespace
    16  
    17  import (
    18  	"context"
    19  
    20  	"github.com/coreos/etcd/clientv3"
    21  	"github.com/coreos/etcd/etcdserver/api/v3rpc/rpctypes"
    22  	pb "github.com/coreos/etcd/etcdserver/etcdserverpb"
    23  )
    24  
    25  type kvPrefix struct {
    26  	clientv3.KV
    27  	pfx string
    28  }
    29  
    30  // NewKV wraps a KV instance so that all requests
    31  // are prefixed with a given string.
    32  func NewKV(kv clientv3.KV, prefix string) clientv3.KV {
    33  	return &kvPrefix{kv, prefix}
    34  }
    35  
    36  func (kv *kvPrefix) Put(ctx context.Context, key, val string, opts ...clientv3.OpOption) (*clientv3.PutResponse, error) {
    37  	if len(key) == 0 {
    38  		return nil, rpctypes.ErrEmptyKey
    39  	}
    40  	op := kv.prefixOp(clientv3.OpPut(key, val, opts...))
    41  	r, err := kv.KV.Do(ctx, op)
    42  	if err != nil {
    43  		return nil, err
    44  	}
    45  	put := r.Put()
    46  	kv.unprefixPutResponse(put)
    47  	return put, nil
    48  }
    49  
    50  func (kv *kvPrefix) Get(ctx context.Context, key string, opts ...clientv3.OpOption) (*clientv3.GetResponse, error) {
    51  	if len(key) == 0 {
    52  		return nil, rpctypes.ErrEmptyKey
    53  	}
    54  	r, err := kv.KV.Do(ctx, kv.prefixOp(clientv3.OpGet(key, opts...)))
    55  	if err != nil {
    56  		return nil, err
    57  	}
    58  	get := r.Get()
    59  	kv.unprefixGetResponse(get)
    60  	return get, nil
    61  }
    62  
    63  func (kv *kvPrefix) Delete(ctx context.Context, key string, opts ...clientv3.OpOption) (*clientv3.DeleteResponse, error) {
    64  	if len(key) == 0 {
    65  		return nil, rpctypes.ErrEmptyKey
    66  	}
    67  	r, err := kv.KV.Do(ctx, kv.prefixOp(clientv3.OpDelete(key, opts...)))
    68  	if err != nil {
    69  		return nil, err
    70  	}
    71  	del := r.Del()
    72  	kv.unprefixDeleteResponse(del)
    73  	return del, nil
    74  }
    75  
    76  func (kv *kvPrefix) Do(ctx context.Context, op clientv3.Op) (clientv3.OpResponse, error) {
    77  	if len(op.KeyBytes()) == 0 && !op.IsTxn() {
    78  		return clientv3.OpResponse{}, rpctypes.ErrEmptyKey
    79  	}
    80  	r, err := kv.KV.Do(ctx, kv.prefixOp(op))
    81  	if err != nil {
    82  		return r, err
    83  	}
    84  	switch {
    85  	case r.Get() != nil:
    86  		kv.unprefixGetResponse(r.Get())
    87  	case r.Put() != nil:
    88  		kv.unprefixPutResponse(r.Put())
    89  	case r.Del() != nil:
    90  		kv.unprefixDeleteResponse(r.Del())
    91  	case r.Txn() != nil:
    92  		kv.unprefixTxnResponse(r.Txn())
    93  	}
    94  	return r, nil
    95  }
    96  
    97  type txnPrefix struct {
    98  	clientv3.Txn
    99  	kv *kvPrefix
   100  }
   101  
   102  func (kv *kvPrefix) Txn(ctx context.Context) clientv3.Txn {
   103  	return &txnPrefix{kv.KV.Txn(ctx), kv}
   104  }
   105  
   106  func (txn *txnPrefix) If(cs ...clientv3.Cmp) clientv3.Txn {
   107  	txn.Txn = txn.Txn.If(txn.kv.prefixCmps(cs)...)
   108  	return txn
   109  }
   110  
   111  func (txn *txnPrefix) Then(ops ...clientv3.Op) clientv3.Txn {
   112  	txn.Txn = txn.Txn.Then(txn.kv.prefixOps(ops)...)
   113  	return txn
   114  }
   115  
   116  func (txn *txnPrefix) Else(ops ...clientv3.Op) clientv3.Txn {
   117  	txn.Txn = txn.Txn.Else(txn.kv.prefixOps(ops)...)
   118  	return txn
   119  }
   120  
   121  func (txn *txnPrefix) Commit() (*clientv3.TxnResponse, error) {
   122  	resp, err := txn.Txn.Commit()
   123  	if err != nil {
   124  		return nil, err
   125  	}
   126  	txn.kv.unprefixTxnResponse(resp)
   127  	return resp, nil
   128  }
   129  
   130  func (kv *kvPrefix) prefixOp(op clientv3.Op) clientv3.Op {
   131  	if !op.IsTxn() {
   132  		begin, end := kv.prefixInterval(op.KeyBytes(), op.RangeBytes())
   133  		op.WithKeyBytes(begin)
   134  		op.WithRangeBytes(end)
   135  		return op
   136  	}
   137  	cmps, thenOps, elseOps := op.Txn()
   138  	return clientv3.OpTxn(kv.prefixCmps(cmps), kv.prefixOps(thenOps), kv.prefixOps(elseOps))
   139  }
   140  
   141  func (kv *kvPrefix) unprefixGetResponse(resp *clientv3.GetResponse) {
   142  	for i := range resp.Kvs {
   143  		resp.Kvs[i].Key = resp.Kvs[i].Key[len(kv.pfx):]
   144  	}
   145  }
   146  
   147  func (kv *kvPrefix) unprefixPutResponse(resp *clientv3.PutResponse) {
   148  	if resp.PrevKv != nil {
   149  		resp.PrevKv.Key = resp.PrevKv.Key[len(kv.pfx):]
   150  	}
   151  }
   152  
   153  func (kv *kvPrefix) unprefixDeleteResponse(resp *clientv3.DeleteResponse) {
   154  	for i := range resp.PrevKvs {
   155  		resp.PrevKvs[i].Key = resp.PrevKvs[i].Key[len(kv.pfx):]
   156  	}
   157  }
   158  
   159  func (kv *kvPrefix) unprefixTxnResponse(resp *clientv3.TxnResponse) {
   160  	for _, r := range resp.Responses {
   161  		switch tv := r.Response.(type) {
   162  		case *pb.ResponseOp_ResponseRange:
   163  			if tv.ResponseRange != nil {
   164  				kv.unprefixGetResponse((*clientv3.GetResponse)(tv.ResponseRange))
   165  			}
   166  		case *pb.ResponseOp_ResponsePut:
   167  			if tv.ResponsePut != nil {
   168  				kv.unprefixPutResponse((*clientv3.PutResponse)(tv.ResponsePut))
   169  			}
   170  		case *pb.ResponseOp_ResponseDeleteRange:
   171  			if tv.ResponseDeleteRange != nil {
   172  				kv.unprefixDeleteResponse((*clientv3.DeleteResponse)(tv.ResponseDeleteRange))
   173  			}
   174  		case *pb.ResponseOp_ResponseTxn:
   175  			if tv.ResponseTxn != nil {
   176  				kv.unprefixTxnResponse((*clientv3.TxnResponse)(tv.ResponseTxn))
   177  			}
   178  		default:
   179  		}
   180  	}
   181  }
   182  
   183  func (kv *kvPrefix) prefixInterval(key, end []byte) (pfxKey []byte, pfxEnd []byte) {
   184  	return prefixInterval(kv.pfx, key, end)
   185  }
   186  
   187  func (kv *kvPrefix) prefixCmps(cs []clientv3.Cmp) []clientv3.Cmp {
   188  	newCmps := make([]clientv3.Cmp, len(cs))
   189  	for i := range cs {
   190  		newCmps[i] = cs[i]
   191  		pfxKey, endKey := kv.prefixInterval(cs[i].KeyBytes(), cs[i].RangeEnd)
   192  		newCmps[i].WithKeyBytes(pfxKey)
   193  		if len(cs[i].RangeEnd) != 0 {
   194  			newCmps[i].RangeEnd = endKey
   195  		}
   196  	}
   197  	return newCmps
   198  }
   199  
   200  func (kv *kvPrefix) prefixOps(ops []clientv3.Op) []clientv3.Op {
   201  	newOps := make([]clientv3.Op, len(ops))
   202  	for i := range ops {
   203  		newOps[i] = kv.prefixOp(ops[i])
   204  	}
   205  	return newOps
   206  }