• kv.go



    package clientv3

    import (
        pb "github.com/coreos/etcd/etcdserver/etcdserverpb"   //protobuffer  
        "golang.org/x/net/context"  
        "google.golang.org/grpc"   //google  rpc 框架
    )

    type (
        CompactResponse pb.CompactionResponse  //带压缩的响应
        PutResponse     pb.PutResponse   //添加响应
        GetResponse     pb.RangeResponse  // 带区间的响应
        DeleteResponse  pb.DeleteRangeResponse  // 删除带区间数据的响应
        TxnResponse     pb.TxnResponse    //带事务的响应
    )

    type KV interface {
        // Put puts a key-value pair into etcd.
            //添加键值对到etcd中
        // Note that key,value can be plain bytes array and string is
        // an immutable representation of that bytes array.
           //注意:键值对可以是字节数组或者字符串  字符串是原子性的字节数组
        // To get a string of bytes, do string([]byte(0x10, 0x20)).
            //
        Put(ctx context.Context, key, val string, opts ...OpOption) (*PutResponse, error)

        // Get retrieves keys.
            //获取键对应的值
        // By default, Get will return the value for "key", if any.
            //默认 获取键对应的值  在任何情况下
        // When passed WithRange(end), Get will return the keys in the range [key, end).
            //当opts 使用了 WithRange(end),将得到键对应的区间[key, end)之间的值
        // When passed WithFromKey(), Get returns keys greater than or equal to key.
                 //opts 使用了WithFromKey(),得到大于等于当前key 对应的value
        // When passed WithRev(rev) with rev > 0, Get retrieves keys at the given revision;
                    //当opts 使用了 WithRev(rev),如果版本号rev>0 获取指定的版本号对应的value
        // if the required revision is compacted, the request will fail with ErrCompacted .
        // When passed WithLimit(limit), the number of returned keys is bounded by limit.
                 //当opts 使用了 WithLimit(limit),将得到键对应的区间[key最小值  默认的   end [limit   )的值   例如:  key为 foo   实际的key为 fooN。。。。到foolimit  之间对应的value
        // When passed WithSort(), the keys will be sorted.
                 //当opts 使用了 WithSort(),得到的值将排序  按照字典的顺序来排序
        Get(ctx context.Context, key string, opts ...OpOption) (*GetResponse, error)

        // Delete deletes a key, or optionally using WithRange(end), [key, end).
           //  删除一个键值对    更常使用 WithRange(end), [key, end).
        Delete(ctx context.Context, key string, opts ...OpOption) (*DeleteResponse, error)

        // Compact compacts etcd KV history before the given rev.
                   // 压缩etcd kv历史数据  通常再给出版本号之前
        Compact(ctx context.Context, rev int64, opts ...CompactOption) (*CompactResponse, error)

        // Do applies a single Op on KV without a transaction.
            //do应用于单一kv操作项,通常是没有事务的
        // Do is useful when declaring operations to be issued at a later time
           //
        // whereas Get/Put/Delete are for better suited for when the operation
        // should be immediately issued at time of declaration.

        // Do applies a single Op on KV without a transaction.
        // Do is useful when creating arbitrary operations to be issued at a
        // later time; the user can range over the operations, calling Do to
        // execute them. Get/Put/Delete, on the other hand, are best suited
        // for when the operation should be issued at the time of declaration.
        Do(ctx context.Context, op Op) (OpResponse, error)

        // Txn creates a transaction.
            //创建事务
        Txn(ctx context.Context) Txn
    }
    //响应结构体
    type OpResponse struct {
        put *PutResponse
        get *GetResponse
        del *DeleteResponse
    }

    func (op OpResponse) Put() *PutResponse    { return op.put }
    func (op OpResponse) Get() *GetResponse    { return op.get }
    func (op OpResponse) Del() *DeleteResponse { return op.del }
    //kv存储服务客户端的包装
    type kv struct {
        remote pb.KVClient
    }
    //创建kv 服务  带着指定的客户端
    func NewKV(c *Client) KV {
        return &kv{remote: RetryKVClient(c)}
    }
    //创建一个kv服务客户端  带着指定的protobuffer 客户端
    func NewKVFromKVClient(remote pb.KVClient) KV {
        return &kv{remote: remote}
    }
    //kv结构体实现了 kv接口
    func (kv *kv) Put(ctx context.Context, key, val string, opts ...OpOption) (*PutResponse, error) {
        r, err := kv.Do(ctx, OpPut(key, val, opts...))
        return r.put, toErr(ctx, err)
    }

    func (kv *kv) Get(ctx context.Context, key string, opts ...OpOption) (*GetResponse, error) {
        r, err := kv.Do(ctx, OpGet(key, opts...))
        return r.get, toErr(ctx, err)
    }

    func (kv *kv) Delete(ctx context.Context, key string, opts ...OpOption) (*DeleteResponse, error) {
        r, err := kv.Do(ctx, OpDelete(key, opts...))
        return r.del, toErr(ctx, err)
    }

    func (kv *kv) Compact(ctx context.Context, rev int64, opts ...CompactOption) (*CompactResponse, error) {
        resp, err := kv.remote.Compact(ctx, OpCompact(rev, opts...).toRequest())
        if err != nil {
            return nil, toErr(ctx, err)
        }
        return (*CompactResponse)(resp), err
    }

    func (kv *kv) Txn(ctx context.Context) Txn {
        return &txn{
            kv:  kv,
            ctx: ctx,
        }
    }

    func (kv *kv) Do(ctx context.Context, op Op) (OpResponse, error) {
        for {
            resp, err := kv.do(ctx, op)
            if err == nil {
                return resp, nil
            }

            if isHaltErr(ctx, err) {
                return resp, toErr(ctx, err)
            }
            // do not retry on modifications
            if op.isWrite() {
                return resp, toErr(ctx, err)
            }
        }
    }

    func (kv *kv) do(ctx context.Context, op Op) (OpResponse, error) {
        var err error
        switch op.t {
        // TODO: handle other ops
        case tRange:
            var resp *pb.RangeResponse
            resp, err = kv.remote.Range(ctx, op.toRangeRequest(), grpc.FailFast(false))
            if err == nil {
                return OpResponse{get: (*GetResponse)(resp)}, nil
            }
        case tPut:
            var resp *pb.PutResponse
            r := &pb.PutRequest{Key: op.key, Value: op.val, Lease: int64(op.leaseID), PrevKv: op.prevKV}
            resp, err = kv.remote.Put(ctx, r)
            if err == nil {
                return OpResponse{put: (*PutResponse)(resp)}, nil
            }
        case tDeleteRange:
            var resp *pb.DeleteRangeResponse
            r := &pb.DeleteRangeRequest{Key: op.key, RangeEnd: op.end, PrevKv: op.prevKV}
            resp, err = kv.remote.DeleteRange(ctx, r)
            if err == nil {
                return OpResponse{del: (*DeleteResponse)(resp)}, nil
            }
        default:
            panic("Unknown op")
        }
        return OpResponse{}, err
    }

  • 相关阅读:
    Win7双击任务栏图标导致窗口还原的问题
    一致性哈希算法及其在分布式系统中的应用(转)
    CAP理论(转)
    从Android界面开发谈起(转)
    Android开发入门之Window 环境概念介绍(转)
    数据库缓存技术(转)
    VoltDB开篇 简介(转)
    window下如何让php支持openssl(转)
    mysql分表的3种方法(转)
    linux crontab 每10秒执行一次
  • 原文地址:https://www.cnblogs.com/zhangboyu/p/7452644.html
Copyright © 2020-2023  润新知