diff --git a/Documentation/dev-guide/api_reference_v3.md b/Documentation/dev-guide/api_reference_v3.md index 578724654c6..cf3a08e9229 100644 --- a/Documentation/dev-guide/api_reference_v3.md +++ b/Documentation/dev-guide/api_reference_v3.md @@ -669,6 +669,7 @@ Empty field. | request_range | | RangeRequest | | request_put | | PutRequest | | request_delete_range | | DeleteRangeRequest | +| request_txn | | TxnRequest | @@ -691,6 +692,7 @@ Empty field. | response_range | | RangeResponse | | response_put | | PutResponse | | response_delete_range | | DeleteRangeResponse | +| response_txn | | TxnResponse | diff --git a/Documentation/dev-guide/apispec/swagger/rpc.swagger.json b/Documentation/dev-guide/apispec/swagger/rpc.swagger.json index ed487f991a3..bb14f4f26c1 100644 --- a/Documentation/dev-guide/apispec/swagger/rpc.swagger.json +++ b/Documentation/dev-guide/apispec/swagger/rpc.swagger.json @@ -1954,6 +1954,9 @@ }, "request_range": { "$ref": "#/definitions/etcdserverpbRangeRequest" + }, + "request_txn": { + "$ref": "#/definitions/etcdserverpbTxnRequest" } } }, @@ -1993,6 +1996,9 @@ }, "response_range": { "$ref": "#/definitions/etcdserverpbRangeResponse" + }, + "response_txn": { + "$ref": "#/definitions/etcdserverpbTxnResponse" } } }, diff --git a/clientv3/integration/txn_test.go b/clientv3/integration/txn_test.go index cbfc59e6716..e895b5b625d 100644 --- a/clientv3/integration/txn_test.go +++ b/clientv3/integration/txn_test.go @@ -106,27 +106,35 @@ func TestTxnReadRetry(t *testing.T) { defer clus.Terminate(t) kv := clus.Client(0) - clus.Members[0].Stop(t) - <-clus.Members[0].StopNotify() - donec := make(chan struct{}) - go func() { - ctx := context.TODO() - _, err := kv.Txn(ctx).Then(clientv3.OpGet("foo")).Commit() - if err != nil { - t.Fatalf("expected response, got error %v", err) + thenOps := [][]clientv3.Op{ + {clientv3.OpGet("foo")}, + {clientv3.OpTxn(nil, []clientv3.Op{clientv3.OpGet("foo")}, nil)}, + {clientv3.OpTxn(nil, nil, nil)}, + {}, + } + for i := range thenOps { + clus.Members[0].Stop(t) + <-clus.Members[0].StopNotify() + + donec := make(chan struct{}) + go func() { + _, err := kv.Txn(context.TODO()).Then(thenOps[i]...).Commit() + if err != nil { + t.Fatalf("expected response, got error %v", err) + } + donec <- struct{}{} + }() + // wait for txn to fail on disconnect + time.Sleep(100 * time.Millisecond) + + // restart node; client should resume + clus.Members[0].Restart(t) + select { + case <-donec: + case <-time.After(2 * clus.Members[1].ServerConfig.ReqTimeout()): + t.Fatalf("waited too long") } - donec <- struct{}{} - }() - // wait for txn to fail on disconnect - time.Sleep(100 * time.Millisecond) - - // restart node; client should resume - clus.Members[0].Restart(t) - select { - case <-donec: - case <-time.After(2 * clus.Members[1].ServerConfig.ReqTimeout()): - t.Fatalf("waited too long") } } @@ -179,3 +187,41 @@ func TestTxnCompareRange(t *testing.T) { t.Fatal("expected prefix compare to false, got compares as true") } } + +func TestTxnNested(t *testing.T) { + defer testutil.AfterTest(t) + + clus := integration.NewClusterV3(t, &integration.ClusterConfig{Size: 3}) + defer clus.Terminate(t) + + kv := clus.Client(0) + + tresp, err := kv.Txn(context.TODO()). + If(clientv3.Compare(clientv3.Version("foo"), "=", 0)). + Then( + clientv3.OpPut("foo", "bar"), + clientv3.OpTxn(nil, []clientv3.Op{clientv3.OpPut("abc", "123")}, nil)). + Else(clientv3.OpPut("foo", "baz")).Commit() + if err != nil { + t.Fatal(err) + } + if len(tresp.Responses) != 2 { + t.Errorf("expected 2 top-level txn responses, got %+v", tresp.Responses) + } + + // check txn writes were applied + resp, err := kv.Get(context.TODO(), "foo") + if err != nil { + t.Fatal(err) + } + if len(resp.Kvs) != 1 || string(resp.Kvs[0].Value) != "bar" { + t.Errorf("unexpected Get response %+v", resp) + } + resp, err = kv.Get(context.TODO(), "abc") + if err != nil { + t.Fatal(err) + } + if len(resp.Kvs) != 1 || string(resp.Kvs[0].Value) != "123" { + t.Errorf("unexpected Get response %+v", resp) + } +} diff --git a/clientv3/kv.go b/clientv3/kv.go index dc45fa4ad06..f887e044102 100644 --- a/clientv3/kv.go +++ b/clientv3/kv.go @@ -66,11 +66,13 @@ type OpResponse struct { put *PutResponse get *GetResponse del *DeleteResponse + txn *TxnResponse } func (op OpResponse) Put() *PutResponse { return op.put } func (op OpResponse) Get() *GetResponse { return op.get } func (op OpResponse) Del() *DeleteResponse { return op.del } +func (op OpResponse) Txn() *TxnResponse { return op.txn } type kv struct { remote pb.KVClient @@ -134,7 +136,6 @@ func (kv *kv) Do(ctx context.Context, op Op) (OpResponse, error) { 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)) @@ -155,6 +156,12 @@ func (kv *kv) do(ctx context.Context, op Op) (OpResponse, error) { if err == nil { return OpResponse{del: (*DeleteResponse)(resp)}, nil } + case tTxn: + var resp *pb.TxnResponse + resp, err = kv.remote.Txn(ctx, op.toTxnRequest()) + if err == nil { + return OpResponse{txn: (*TxnResponse)(resp)}, nil + } default: panic("Unknown op") } diff --git a/clientv3/namespace/kv.go b/clientv3/namespace/kv.go index dc013742b01..b5ec5e964e9 100644 --- a/clientv3/namespace/kv.go +++ b/clientv3/namespace/kv.go @@ -74,7 +74,7 @@ func (kv *kvPrefix) Delete(ctx context.Context, key string, opts ...clientv3.OpO } func (kv *kvPrefix) Do(ctx context.Context, op clientv3.Op) (clientv3.OpResponse, error) { - if len(op.KeyBytes()) == 0 { + if len(op.KeyBytes()) == 0 && !op.IsTxn() { return clientv3.OpResponse{}, rpctypes.ErrEmptyKey } r, err := kv.KV.Do(ctx, kv.prefixOp(op)) @@ -88,6 +88,8 @@ func (kv *kvPrefix) Do(ctx context.Context, op clientv3.Op) (clientv3.OpResponse kv.unprefixPutResponse(r.Put()) case r.Del() != nil: kv.unprefixDeleteResponse(r.Del()) + case r.Txn() != nil: + kv.unprefixTxnResponse(r.Txn()) } return r, nil } @@ -102,34 +104,17 @@ func (kv *kvPrefix) Txn(ctx context.Context) clientv3.Txn { } func (txn *txnPrefix) If(cs ...clientv3.Cmp) clientv3.Txn { - newCmps := make([]clientv3.Cmp, len(cs)) - for i := range cs { - newCmps[i] = cs[i] - pfxKey, endKey := txn.kv.prefixInterval(cs[i].KeyBytes(), cs[i].RangeEnd) - newCmps[i].WithKeyBytes(pfxKey) - if len(cs[i].RangeEnd) != 0 { - newCmps[i].RangeEnd = endKey - } - } - txn.Txn = txn.Txn.If(newCmps...) + txn.Txn = txn.Txn.If(txn.kv.prefixCmps(cs)...) return txn } func (txn *txnPrefix) Then(ops ...clientv3.Op) clientv3.Txn { - newOps := make([]clientv3.Op, len(ops)) - for i := range ops { - newOps[i] = txn.kv.prefixOp(ops[i]) - } - txn.Txn = txn.Txn.Then(newOps...) + txn.Txn = txn.Txn.Then(txn.kv.prefixOps(ops)...) return txn } func (txn *txnPrefix) Else(ops ...clientv3.Op) clientv3.Txn { - newOps := make([]clientv3.Op, len(ops)) - for i := range ops { - newOps[i] = txn.kv.prefixOp(ops[i]) - } - txn.Txn = txn.Txn.Else(newOps...) + txn.Txn = txn.Txn.Else(txn.kv.prefixOps(ops)...) return txn } @@ -143,10 +128,14 @@ func (txn *txnPrefix) Commit() (*clientv3.TxnResponse, error) { } func (kv *kvPrefix) prefixOp(op clientv3.Op) clientv3.Op { - begin, end := kv.prefixInterval(op.KeyBytes(), op.RangeBytes()) - op.WithKeyBytes(begin) - op.WithRangeBytes(end) - return op + if !op.IsTxn() { + begin, end := kv.prefixInterval(op.KeyBytes(), op.RangeBytes()) + op.WithKeyBytes(begin) + op.WithRangeBytes(end) + return op + } + cmps, thenOps, elseOps := op.Txn() + return clientv3.OpTxn(kv.prefixCmps(cmps), kv.prefixOps(thenOps), kv.prefixOps(elseOps)) } func (kv *kvPrefix) unprefixGetResponse(resp *clientv3.GetResponse) { @@ -182,6 +171,10 @@ func (kv *kvPrefix) unprefixTxnResponse(resp *clientv3.TxnResponse) { if tv.ResponseDeleteRange != nil { kv.unprefixDeleteResponse((*clientv3.DeleteResponse)(tv.ResponseDeleteRange)) } + case *pb.ResponseOp_ResponseTxn: + if tv.ResponseTxn != nil { + kv.unprefixTxnResponse((*clientv3.TxnResponse)(tv.ResponseTxn)) + } default: } } @@ -190,3 +183,24 @@ func (kv *kvPrefix) unprefixTxnResponse(resp *clientv3.TxnResponse) { func (p *kvPrefix) prefixInterval(key, end []byte) (pfxKey []byte, pfxEnd []byte) { return prefixInterval(p.pfx, key, end) } + +func (kv *kvPrefix) prefixCmps(cs []clientv3.Cmp) []clientv3.Cmp { + newCmps := make([]clientv3.Cmp, len(cs)) + for i := range cs { + newCmps[i] = cs[i] + pfxKey, endKey := kv.prefixInterval(cs[i].KeyBytes(), cs[i].RangeEnd) + newCmps[i].WithKeyBytes(pfxKey) + if len(cs[i].RangeEnd) != 0 { + newCmps[i].RangeEnd = endKey + } + } + return newCmps +} + +func (kv *kvPrefix) prefixOps(ops []clientv3.Op) []clientv3.Op { + newOps := make([]clientv3.Op, len(ops)) + for i := range ops { + newOps[i] = kv.prefixOp(ops[i]) + } + return newOps +} diff --git a/clientv3/op.go b/clientv3/op.go index 63b99501e82..ef6f04368a3 100644 --- a/clientv3/op.go +++ b/clientv3/op.go @@ -23,6 +23,7 @@ const ( tRange opType = iota + 1 tPut tDeleteRange + tTxn ) var ( @@ -67,10 +68,18 @@ type Op struct { // for put val []byte leaseID LeaseID + + // txn + cmps []Cmp + thenOps []Op + elseOps []Op } // accesors / mutators +func (op Op) IsTxn() bool { return op.t == tTxn } +func (op Op) Txn() ([]Cmp, []Op, []Op) { return op.cmps, op.thenOps, op.elseOps } + // KeyBytes returns the byte slice holding the Op's key. func (op Op) KeyBytes() []byte { return op.key } @@ -113,6 +122,22 @@ func (op Op) toRangeRequest() *pb.RangeRequest { return r } +func (op Op) toTxnRequest() *pb.TxnRequest { + thenOps := make([]*pb.RequestOp, len(op.thenOps)) + for i, tOp := range op.thenOps { + thenOps[i] = tOp.toRequestOp() + } + elseOps := make([]*pb.RequestOp, len(op.elseOps)) + for i, eOp := range op.elseOps { + elseOps[i] = eOp.toRequestOp() + } + cmps := make([]*pb.Compare, len(op.cmps)) + for i := range op.cmps { + cmps[i] = (*pb.Compare)(&op.cmps[i]) + } + return &pb.TxnRequest{Compare: cmps, Success: thenOps, Failure: elseOps} +} + func (op Op) toRequestOp() *pb.RequestOp { switch op.t { case tRange: @@ -123,12 +148,27 @@ func (op Op) toRequestOp() *pb.RequestOp { case tDeleteRange: r := &pb.DeleteRangeRequest{Key: op.key, RangeEnd: op.end, PrevKv: op.prevKV} return &pb.RequestOp{Request: &pb.RequestOp_RequestDeleteRange{RequestDeleteRange: r}} + case tTxn: + return &pb.RequestOp{Request: &pb.RequestOp_RequestTxn{RequestTxn: op.toTxnRequest()}} default: panic("Unknown Op") } } func (op Op) isWrite() bool { + if op.t == tTxn { + for _, tOp := range op.thenOps { + if tOp.isWrite() { + return true + } + } + for _, tOp := range op.elseOps { + if tOp.isWrite() { + return true + } + } + return false + } return op.t != tRange } @@ -194,6 +234,10 @@ func OpPut(key, val string, opts ...OpOption) Op { return ret } +func OpTxn(cmps []Cmp, thenOps []Op, elseOps []Op) Op { + return Op{t: tTxn, cmps: cmps, thenOps: thenOps, elseOps: elseOps} +} + func opWatch(key string, opts ...OpOption) Op { ret := Op{t: tRange, key: []byte(key)} ret.applyOpts(opts) diff --git a/etcdserver/api/v3rpc/key.go b/etcdserver/api/v3rpc/key.go index 3f977b74918..973346592de 100644 --- a/etcdserver/api/v3rpc/key.go +++ b/etcdserver/api/v3rpc/key.go @@ -16,11 +16,10 @@ package v3rpc import ( - "sort" - "github.com/coreos/etcd/etcdserver" "github.com/coreos/etcd/etcdserver/api/v3rpc/rpctypes" pb "github.com/coreos/etcd/etcdserver/etcdserverpb" + "github.com/coreos/etcd/pkg/adt" "github.com/coreos/pkg/capnslog" "golang.org/x/net/context" ) @@ -89,6 +88,13 @@ func (s *kvServer) Txn(ctx context.Context, r *pb.TxnRequest) (*pb.TxnResponse, if err := checkTxnRequest(r, int(s.maxTxnOps)); err != nil { return nil, err } + // check for forbidden put/del overlaps after checking request to avoid quadratic blowup + if _, _, err := checkIntervals(r.Success); err != nil { + return nil, err + } + if _, _, err := checkIntervals(r.Failure); err != nil { + return nil, err + } resp, err := s.kv.Txn(ctx, r) if err != nil { @@ -137,7 +143,14 @@ func checkDeleteRequest(r *pb.DeleteRangeRequest) error { } func checkTxnRequest(r *pb.TxnRequest, maxTxnOps int) error { - if len(r.Compare) > maxTxnOps || len(r.Success) > maxTxnOps || len(r.Failure) > maxTxnOps { + opc := len(r.Compare) + if opc < len(r.Success) { + opc = len(r.Success) + } + if opc < len(r.Failure) { + opc = len(r.Failure) + } + if opc > maxTxnOps { return rpctypes.ErrGRPCTooManyOps } @@ -146,100 +159,117 @@ func checkTxnRequest(r *pb.TxnRequest, maxTxnOps int) error { return rpctypes.ErrGRPCEmptyKey } } - for _, u := range r.Success { - if err := checkRequestOp(u); err != nil { + if err := checkRequestOp(u, maxTxnOps-opc); err != nil { return err } } - if err := checkRequestDupKeys(r.Success); err != nil { - return err - } - for _, u := range r.Failure { - if err := checkRequestOp(u); err != nil { + if err := checkRequestOp(u, maxTxnOps-opc); err != nil { return err } } - return checkRequestDupKeys(r.Failure) + + return nil } -// checkRequestDupKeys gives rpctypes.ErrGRPCDuplicateKey if the same key is modified twice -func checkRequestDupKeys(reqs []*pb.RequestOp) error { - // check put overlap - keys := make(map[string]struct{}) - for _, requ := range reqs { - tv, ok := requ.Request.(*pb.RequestOp_RequestPut) +// checkIntervals tests whether puts and deletes overlap for a list of ops. If +// there is an overlap, returns an error. If no overlap, return put and delete +// sets for recursive evaluation. +func checkIntervals(reqs []*pb.RequestOp) (map[string]struct{}, adt.IntervalTree, error) { + var dels adt.IntervalTree + + // collect deletes from this level; build first to check lower level overlapped puts + for _, req := range reqs { + tv, ok := req.Request.(*pb.RequestOp_RequestDeleteRange) if !ok { continue } - preq := tv.RequestPut - if preq == nil { + dreq := tv.RequestDeleteRange + if dreq == nil { continue } - if _, ok := keys[string(preq.Key)]; ok { - return rpctypes.ErrGRPCDuplicateKey + var iv adt.Interval + if len(dreq.RangeEnd) != 0 { + iv = adt.NewStringAffineInterval(string(dreq.Key), string(dreq.RangeEnd)) + } else { + iv = adt.NewStringAffinePoint(string(dreq.Key)) } - keys[string(preq.Key)] = struct{}{} - } - - // no need to check deletes if no puts; delete overlaps are permitted - if len(keys) == 0 { - return nil - } - - // sort keys for range checking - sortedKeys := []string{} - for k := range keys { - sortedKeys = append(sortedKeys, k) + dels.Insert(iv, struct{}{}) } - sort.Strings(sortedKeys) - // check put overlap with deletes - for _, requ := range reqs { - tv, ok := requ.Request.(*pb.RequestOp_RequestDeleteRange) + // collect children puts/deletes + puts := make(map[string]struct{}) + for _, req := range reqs { + tv, ok := req.Request.(*pb.RequestOp_RequestTxn) if !ok { continue } - dreq := tv.RequestDeleteRange - if dreq == nil { - continue + putsThen, delsThen, err := checkIntervals(tv.RequestTxn.Success) + if err != nil { + return nil, dels, err + } + putsElse, delsElse, err := checkIntervals(tv.RequestTxn.Failure) + if err != nil { + return nil, dels, err } - if dreq.RangeEnd == nil { - if _, found := keys[string(dreq.Key)]; found { - return rpctypes.ErrGRPCDuplicateKey + for k := range putsThen { + if _, ok := puts[k]; ok { + return nil, dels, rpctypes.ErrGRPCDuplicateKey } - } else { - lo := sort.SearchStrings(sortedKeys, string(dreq.Key)) - hi := sort.SearchStrings(sortedKeys, string(dreq.RangeEnd)) - if lo != hi { - // element between lo and hi => overlap - return rpctypes.ErrGRPCDuplicateKey + if dels.Intersects(adt.NewStringAffinePoint(k)) { + return nil, dels, rpctypes.ErrGRPCDuplicateKey } + puts[k] = struct{}{} } + for k := range putsElse { + if _, ok := puts[k]; ok { + // if key is from putsThen, overlap is OK since + // either then/else are mutually exclusive + if _, isSafe := putsThen[k]; !isSafe { + return nil, dels, rpctypes.ErrGRPCDuplicateKey + } + } + if dels.Intersects(adt.NewStringAffinePoint(k)) { + return nil, dels, rpctypes.ErrGRPCDuplicateKey + } + puts[k] = struct{}{} + } + dels.Union(delsThen, adt.NewStringAffineInterval("\x00", "")) + dels.Union(delsElse, adt.NewStringAffineInterval("\x00", "")) } - return nil + // collect and check this level's puts + for _, req := range reqs { + tv, ok := req.Request.(*pb.RequestOp_RequestPut) + if !ok || tv.RequestPut == nil { + continue + } + k := string(tv.RequestPut.Key) + if _, ok := puts[k]; ok { + return nil, dels, rpctypes.ErrGRPCDuplicateKey + } + if dels.Intersects(adt.NewStringAffinePoint(k)) { + return nil, dels, rpctypes.ErrGRPCDuplicateKey + } + puts[k] = struct{}{} + } + return puts, dels, nil } -func checkRequestOp(u *pb.RequestOp) error { +func checkRequestOp(u *pb.RequestOp, maxTxnOps int) error { // TODO: ensure only one of the field is set. switch uv := u.Request.(type) { case *pb.RequestOp_RequestRange: - if uv.RequestRange != nil { - return checkRangeRequest(uv.RequestRange) - } + return checkRangeRequest(uv.RequestRange) case *pb.RequestOp_RequestPut: - if uv.RequestPut != nil { - return checkPutRequest(uv.RequestPut) - } + return checkPutRequest(uv.RequestPut) case *pb.RequestOp_RequestDeleteRange: - if uv.RequestDeleteRange != nil { - return checkDeleteRequest(uv.RequestDeleteRange) - } + return checkDeleteRequest(uv.RequestDeleteRange) + case *pb.RequestOp_RequestTxn: + return checkTxnRequest(uv.RequestTxn, maxTxnOps) default: // empty op / nil entry return rpctypes.ErrGRPCKeyNotFound } - return nil } diff --git a/etcdserver/apply.go b/etcdserver/apply.go index 707ac89f0a0..3aa8d71e680 100644 --- a/etcdserver/apply.go +++ b/etcdserver/apply.go @@ -76,14 +76,30 @@ type applierV3 interface { RoleList(ua *pb.AuthRoleListRequest) (*pb.AuthRoleListResponse, error) } +type checkReqFunc func(mvcc.ReadView, *pb.RequestOp) error + type applierV3backend struct { s *EtcdServer + + checkPut checkReqFunc + checkRange checkReqFunc +} + +func (s *EtcdServer) newApplierV3Backend() applierV3 { + base := &applierV3backend{s: s} + base.checkPut = func(rv mvcc.ReadView, req *pb.RequestOp) error { + return base.checkRequestPut(rv, req) + } + base.checkRange = func(rv mvcc.ReadView, req *pb.RequestOp) error { + return base.checkRequestRange(rv, req) + } + return base } func (s *EtcdServer) newApplierV3() applierV3 { return newAuthApplierV3( s.AuthStore(), - newQuotaApplierV3(s, &applierV3backend{s}), + newQuotaApplierV3(s, s.newApplierV3Backend()), s.lessor, ) } @@ -315,24 +331,19 @@ func (a *applierV3backend) Txn(rt *pb.TxnRequest) (*pb.TxnResponse, error) { isWrite := !isTxnReadonly(rt) txn := mvcc.NewReadOnlyTxnWrite(a.s.KV().Read()) - reqs, ok := a.compareToOps(txn, rt) + txnPath := compareToPath(txn, rt) if isWrite { - if err := a.checkRequestPut(txn, reqs); err != nil { + if _, err := checkRequests(txn, rt, txnPath, a.checkPut); err != nil { txn.End() return nil, err } } - if err := checkRequestRange(txn, reqs); err != nil { + if _, err := checkRequests(txn, rt, txnPath, a.checkRange); err != nil { txn.End() return nil, err } - resps := make([]*pb.ResponseOp, len(reqs)) - txnResp := &pb.TxnResponse{ - Responses: resps, - Succeeded: ok, - Header: &pb.ResponseHeader{}, - } + txnResp, _ := newTxnResp(rt, txnPath) // When executing mutable txn ops, etcd must hold the txn lock so // readers do not see any intermediate results. Since writes are @@ -342,9 +353,7 @@ func (a *applierV3backend) Txn(rt *pb.TxnRequest) (*pb.TxnResponse, error) { txn.End() txn = a.s.KV().Write() } - for i := range reqs { - resps[i] = a.applyUnion(txn, reqs[i]) - } + a.applyTxn(txn, rt, txnPath, txnResp) rev := txn.Rev() if len(txn.Changes()) != 0 { rev++ @@ -355,13 +364,60 @@ func (a *applierV3backend) Txn(rt *pb.TxnRequest) (*pb.TxnResponse, error) { return txnResp, nil } -func (a *applierV3backend) compareToOps(rv mvcc.ReadView, rt *pb.TxnRequest) ([]*pb.RequestOp, bool) { - for _, c := range rt.Compare { +// newTxnResp allocates a txn response for a txn request given a path. +func newTxnResp(rt *pb.TxnRequest, txnPath []bool) (txnResp *pb.TxnResponse, txnCount int) { + reqs := rt.Success + if !txnPath[0] { + reqs = rt.Failure + } + resps := make([]*pb.ResponseOp, len(reqs)) + txnResp = &pb.TxnResponse{ + Responses: resps, + Succeeded: txnPath[0], + Header: &pb.ResponseHeader{}, + } + for i, req := range reqs { + switch tv := req.Request.(type) { + case *pb.RequestOp_RequestRange: + resps[i] = &pb.ResponseOp{Response: &pb.ResponseOp_ResponseRange{}} + case *pb.RequestOp_RequestPut: + resps[i] = &pb.ResponseOp{Response: &pb.ResponseOp_ResponsePut{}} + case *pb.RequestOp_RequestDeleteRange: + resps[i] = &pb.ResponseOp{Response: &pb.ResponseOp_ResponseDeleteRange{}} + case *pb.RequestOp_RequestTxn: + resp, txns := newTxnResp(tv.RequestTxn, txnPath[1:]) + resps[i] = &pb.ResponseOp{Response: &pb.ResponseOp_ResponseTxn{ResponseTxn: resp}} + txnPath = txnPath[1+txns:] + txnCount += txns + 1 + default: + } + } + return txnResp, txnCount +} + +func compareToPath(rv mvcc.ReadView, rt *pb.TxnRequest) []bool { + txnPath := make([]bool, 1) + ops := rt.Success + if txnPath[0] = applyCompares(rv, rt.Compare); !txnPath[0] { + ops = rt.Failure + } + for _, op := range ops { + tv, ok := op.Request.(*pb.RequestOp_RequestTxn) + if !ok || tv.RequestTxn == nil { + continue + } + txnPath = append(txnPath, compareToPath(rv, tv.RequestTxn)...) + } + return txnPath +} + +func applyCompares(rv mvcc.ReadView, cmps []*pb.Compare) bool { + for _, c := range cmps { if !applyCompare(rv, c) { - return rt.Failure, false + return false } } - return rt.Success, true + return true } // applyCompare applies the compare request. @@ -431,38 +487,42 @@ func compareKV(c *pb.Compare, ckv mvccpb.KeyValue) bool { return true } -func (a *applierV3backend) applyUnion(txn mvcc.TxnWrite, union *pb.RequestOp) *pb.ResponseOp { - switch tv := union.Request.(type) { - case *pb.RequestOp_RequestRange: - if tv.RequestRange != nil { +func (a *applierV3backend) applyTxn(txn mvcc.TxnWrite, rt *pb.TxnRequest, txnPath []bool, tresp *pb.TxnResponse) (txns int) { + reqs := rt.Success + if !txnPath[0] { + reqs = rt.Failure + } + for i, req := range reqs { + respi := tresp.Responses[i].Response + switch tv := req.Request.(type) { + case *pb.RequestOp_RequestRange: resp, err := a.Range(txn, tv.RequestRange) if err != nil { plog.Panicf("unexpected error during txn: %v", err) } - return &pb.ResponseOp{Response: &pb.ResponseOp_ResponseRange{ResponseRange: resp}} - } - case *pb.RequestOp_RequestPut: - if tv.RequestPut != nil { + respi.(*pb.ResponseOp_ResponseRange).ResponseRange = resp + case *pb.RequestOp_RequestPut: resp, err := a.Put(txn, tv.RequestPut) if err != nil { plog.Panicf("unexpected error during txn: %v", err) } - return &pb.ResponseOp{Response: &pb.ResponseOp_ResponsePut{ResponsePut: resp}} - } - case *pb.RequestOp_RequestDeleteRange: - if tv.RequestDeleteRange != nil { + respi.(*pb.ResponseOp_ResponsePut).ResponsePut = resp + case *pb.RequestOp_RequestDeleteRange: resp, err := a.DeleteRange(txn, tv.RequestDeleteRange) if err != nil { plog.Panicf("unexpected error during txn: %v", err) } - return &pb.ResponseOp{Response: &pb.ResponseOp_ResponseDeleteRange{ResponseDeleteRange: resp}} + respi.(*pb.ResponseOp_ResponseDeleteRange).ResponseDeleteRange = resp + case *pb.RequestOp_RequestTxn: + resp := respi.(*pb.ResponseOp_ResponseTxn).ResponseTxn + applyTxns := a.applyTxn(txn, tv.RequestTxn, txnPath[1:], resp) + txns += applyTxns + 1 + txnPath = txnPath[applyTxns+1:] + default: + // empty union } - default: - // empty union - return nil } - return nil - + return txns } func (a *applierV3backend) Compaction(compaction *pb.CompactionRequest) (*pb.CompactionResponse, <-chan struct{}, error) { @@ -768,57 +828,70 @@ func (s *kvSortByValue) Less(i, j int) bool { return bytes.Compare(s.kvs[i].Value, s.kvs[j].Value) < 0 } -func (a *applierV3backend) checkRequestPut(rv mvcc.ReadView, reqs []*pb.RequestOp) error { - for _, requ := range reqs { - tv, ok := requ.Request.(*pb.RequestOp_RequestPut) - if !ok { - continue - } - preq := tv.RequestPut - if preq == nil { - continue - } - if preq.IgnoreValue || preq.IgnoreLease { - // expects previous key-value, error if not exist - rr, err := rv.Range(preq.Key, nil, mvcc.RangeOptions{}) +func checkRequests(rv mvcc.ReadView, rt *pb.TxnRequest, txnPath []bool, f checkReqFunc) (int, error) { + txnCount := 0 + reqs := rt.Success + if !txnPath[0] { + reqs = rt.Failure + } + for _, req := range reqs { + if tv, ok := req.Request.(*pb.RequestOp_RequestTxn); ok && tv.RequestTxn != nil { + txns, err := checkRequests(rv, tv.RequestTxn, txnPath[1:], f) if err != nil { - return err + return 0, err } - if rr == nil || len(rr.KVs) == 0 { - return ErrKeyNotFound - } - } - if lease.LeaseID(preq.Lease) == lease.NoLease { + txnCount += txns + 1 + txnPath = txnPath[txns+1:] continue } - if l := a.s.lessor.Lookup(lease.LeaseID(preq.Lease)); l == nil { - return lease.ErrLeaseNotFound + if err := f(rv, req); err != nil { + return 0, err } } - return nil + return txnCount, nil } -func checkRequestRange(rv mvcc.ReadView, reqs []*pb.RequestOp) error { - for _, requ := range reqs { - tv, ok := requ.Request.(*pb.RequestOp_RequestRange) - if !ok { - continue - } - greq := tv.RequestRange - if greq == nil || greq.Revision == 0 { - continue +func (a *applierV3backend) checkRequestPut(rv mvcc.ReadView, reqOp *pb.RequestOp) error { + tv, ok := reqOp.Request.(*pb.RequestOp_RequestPut) + if !ok || tv.RequestPut == nil { + return nil + } + req := tv.RequestPut + if req.IgnoreValue || req.IgnoreLease { + // expects previous key-value, error if not exist + rr, err := rv.Range(req.Key, nil, mvcc.RangeOptions{}) + if err != nil { + return err } - - if greq.Revision > rv.Rev() { - return mvcc.ErrFutureRev + if rr == nil || len(rr.KVs) == 0 { + return ErrKeyNotFound } - if greq.Revision < rv.FirstRev() { - return mvcc.ErrCompacted + } + if lease.LeaseID(req.Lease) != lease.NoLease { + if l := a.s.lessor.Lookup(lease.LeaseID(req.Lease)); l == nil { + return lease.ErrLeaseNotFound } } return nil } +func (a *applierV3backend) checkRequestRange(rv mvcc.ReadView, reqOp *pb.RequestOp) error { + tv, ok := reqOp.Request.(*pb.RequestOp_RequestRange) + if !ok || tv.RequestRange == nil { + return nil + } + req := tv.RequestRange + switch { + case req.Revision == 0: + return nil + case req.Revision > rv.Rev(): + return mvcc.ErrFutureRev + case req.Revision < rv.FirstRev(): + return mvcc.ErrCompacted + } + return nil +} + func compareInt64(a, b int64) int { switch { case a < b: diff --git a/etcdserver/etcdserverpb/rpc.pb.go b/etcdserver/etcdserverpb/rpc.pb.go index 8d56f556dac..04e4c7cdaae 100644 --- a/etcdserver/etcdserverpb/rpc.pb.go +++ b/etcdserver/etcdserverpb/rpc.pb.go @@ -608,6 +608,7 @@ type RequestOp struct { // *RequestOp_RequestRange // *RequestOp_RequestPut // *RequestOp_RequestDeleteRange + // *RequestOp_RequestTxn Request isRequestOp_Request `protobuf_oneof:"request"` } @@ -631,10 +632,14 @@ type RequestOp_RequestPut struct { type RequestOp_RequestDeleteRange struct { RequestDeleteRange *DeleteRangeRequest `protobuf:"bytes,3,opt,name=request_delete_range,json=requestDeleteRange,oneof"` } +type RequestOp_RequestTxn struct { + RequestTxn *TxnRequest `protobuf:"bytes,4,opt,name=request_txn,json=requestTxn,oneof"` +} func (*RequestOp_RequestRange) isRequestOp_Request() {} func (*RequestOp_RequestPut) isRequestOp_Request() {} func (*RequestOp_RequestDeleteRange) isRequestOp_Request() {} +func (*RequestOp_RequestTxn) isRequestOp_Request() {} func (m *RequestOp) GetRequest() isRequestOp_Request { if m != nil { @@ -664,12 +669,20 @@ func (m *RequestOp) GetRequestDeleteRange() *DeleteRangeRequest { return nil } +func (m *RequestOp) GetRequestTxn() *TxnRequest { + if x, ok := m.GetRequest().(*RequestOp_RequestTxn); ok { + return x.RequestTxn + } + return nil +} + // XXX_OneofFuncs is for the internal use of the proto package. func (*RequestOp) XXX_OneofFuncs() (func(msg proto.Message, b *proto.Buffer) error, func(msg proto.Message, tag, wire int, b *proto.Buffer) (bool, error), func(msg proto.Message) (n int), []interface{}) { return _RequestOp_OneofMarshaler, _RequestOp_OneofUnmarshaler, _RequestOp_OneofSizer, []interface{}{ (*RequestOp_RequestRange)(nil), (*RequestOp_RequestPut)(nil), (*RequestOp_RequestDeleteRange)(nil), + (*RequestOp_RequestTxn)(nil), } } @@ -692,6 +705,11 @@ func _RequestOp_OneofMarshaler(msg proto.Message, b *proto.Buffer) error { if err := b.EncodeMessage(x.RequestDeleteRange); err != nil { return err } + case *RequestOp_RequestTxn: + _ = b.EncodeVarint(4<<3 | proto.WireBytes) + if err := b.EncodeMessage(x.RequestTxn); err != nil { + return err + } case nil: default: return fmt.Errorf("RequestOp.Request has unexpected type %T", x) @@ -726,6 +744,14 @@ func _RequestOp_OneofUnmarshaler(msg proto.Message, tag, wire int, b *proto.Buff err := b.DecodeMessage(msg) m.Request = &RequestOp_RequestDeleteRange{msg} return true, err + case 4: // request.request_txn + if wire != proto.WireBytes { + return true, proto.ErrInternalBadWireType + } + msg := new(TxnRequest) + err := b.DecodeMessage(msg) + m.Request = &RequestOp_RequestTxn{msg} + return true, err default: return false, nil } @@ -750,6 +776,11 @@ func _RequestOp_OneofSizer(msg proto.Message) (n int) { n += proto.SizeVarint(3<<3 | proto.WireBytes) n += proto.SizeVarint(uint64(s)) n += s + case *RequestOp_RequestTxn: + s := proto.Size(x.RequestTxn) + n += proto.SizeVarint(4<<3 | proto.WireBytes) + n += proto.SizeVarint(uint64(s)) + n += s case nil: default: panic(fmt.Sprintf("proto: unexpected type %T in oneof", x)) @@ -764,6 +795,7 @@ type ResponseOp struct { // *ResponseOp_ResponseRange // *ResponseOp_ResponsePut // *ResponseOp_ResponseDeleteRange + // *ResponseOp_ResponseTxn Response isResponseOp_Response `protobuf_oneof:"response"` } @@ -787,10 +819,14 @@ type ResponseOp_ResponsePut struct { type ResponseOp_ResponseDeleteRange struct { ResponseDeleteRange *DeleteRangeResponse `protobuf:"bytes,3,opt,name=response_delete_range,json=responseDeleteRange,oneof"` } +type ResponseOp_ResponseTxn struct { + ResponseTxn *TxnResponse `protobuf:"bytes,4,opt,name=response_txn,json=responseTxn,oneof"` +} func (*ResponseOp_ResponseRange) isResponseOp_Response() {} func (*ResponseOp_ResponsePut) isResponseOp_Response() {} func (*ResponseOp_ResponseDeleteRange) isResponseOp_Response() {} +func (*ResponseOp_ResponseTxn) isResponseOp_Response() {} func (m *ResponseOp) GetResponse() isResponseOp_Response { if m != nil { @@ -820,12 +856,20 @@ func (m *ResponseOp) GetResponseDeleteRange() *DeleteRangeResponse { return nil } +func (m *ResponseOp) GetResponseTxn() *TxnResponse { + if x, ok := m.GetResponse().(*ResponseOp_ResponseTxn); ok { + return x.ResponseTxn + } + return nil +} + // XXX_OneofFuncs is for the internal use of the proto package. func (*ResponseOp) XXX_OneofFuncs() (func(msg proto.Message, b *proto.Buffer) error, func(msg proto.Message, tag, wire int, b *proto.Buffer) (bool, error), func(msg proto.Message) (n int), []interface{}) { return _ResponseOp_OneofMarshaler, _ResponseOp_OneofUnmarshaler, _ResponseOp_OneofSizer, []interface{}{ (*ResponseOp_ResponseRange)(nil), (*ResponseOp_ResponsePut)(nil), (*ResponseOp_ResponseDeleteRange)(nil), + (*ResponseOp_ResponseTxn)(nil), } } @@ -848,6 +892,11 @@ func _ResponseOp_OneofMarshaler(msg proto.Message, b *proto.Buffer) error { if err := b.EncodeMessage(x.ResponseDeleteRange); err != nil { return err } + case *ResponseOp_ResponseTxn: + _ = b.EncodeVarint(4<<3 | proto.WireBytes) + if err := b.EncodeMessage(x.ResponseTxn); err != nil { + return err + } case nil: default: return fmt.Errorf("ResponseOp.Response has unexpected type %T", x) @@ -882,6 +931,14 @@ func _ResponseOp_OneofUnmarshaler(msg proto.Message, tag, wire int, b *proto.Buf err := b.DecodeMessage(msg) m.Response = &ResponseOp_ResponseDeleteRange{msg} return true, err + case 4: // response.response_txn + if wire != proto.WireBytes { + return true, proto.ErrInternalBadWireType + } + msg := new(TxnResponse) + err := b.DecodeMessage(msg) + m.Response = &ResponseOp_ResponseTxn{msg} + return true, err default: return false, nil } @@ -906,6 +963,11 @@ func _ResponseOp_OneofSizer(msg proto.Message) (n int) { n += proto.SizeVarint(3<<3 | proto.WireBytes) n += proto.SizeVarint(uint64(s)) n += s + case *ResponseOp_ResponseTxn: + s := proto.Size(x.ResponseTxn) + n += proto.SizeVarint(4<<3 | proto.WireBytes) + n += proto.SizeVarint(uint64(s)) + n += s case nil: default: panic(fmt.Sprintf("proto: unexpected type %T in oneof", x)) @@ -4942,6 +5004,20 @@ func (m *RequestOp_RequestDeleteRange) MarshalTo(dAtA []byte) (int, error) { } return i, nil } +func (m *RequestOp_RequestTxn) MarshalTo(dAtA []byte) (int, error) { + i := 0 + if m.RequestTxn != nil { + dAtA[i] = 0x22 + i++ + i = encodeVarintRpc(dAtA, i, uint64(m.RequestTxn.Size())) + n9, err := m.RequestTxn.MarshalTo(dAtA[i:]) + if err != nil { + return 0, err + } + i += n9 + } + return i, nil +} func (m *ResponseOp) Marshal() (dAtA []byte, err error) { size := m.Size() dAtA = make([]byte, size) @@ -4958,11 +5034,11 @@ func (m *ResponseOp) MarshalTo(dAtA []byte) (int, error) { var l int _ = l if m.Response != nil { - nn9, err := m.Response.MarshalTo(dAtA[i:]) + nn10, err := m.Response.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += nn9 + i += nn10 } return i, nil } @@ -4973,11 +5049,11 @@ func (m *ResponseOp_ResponseRange) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0xa i++ i = encodeVarintRpc(dAtA, i, uint64(m.ResponseRange.Size())) - n10, err := m.ResponseRange.MarshalTo(dAtA[i:]) + n11, err := m.ResponseRange.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n10 + i += n11 } return i, nil } @@ -4987,11 +5063,11 @@ func (m *ResponseOp_ResponsePut) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0x12 i++ i = encodeVarintRpc(dAtA, i, uint64(m.ResponsePut.Size())) - n11, err := m.ResponsePut.MarshalTo(dAtA[i:]) + n12, err := m.ResponsePut.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n11 + i += n12 } return i, nil } @@ -5001,11 +5077,25 @@ func (m *ResponseOp_ResponseDeleteRange) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0x1a i++ i = encodeVarintRpc(dAtA, i, uint64(m.ResponseDeleteRange.Size())) - n12, err := m.ResponseDeleteRange.MarshalTo(dAtA[i:]) + n13, err := m.ResponseDeleteRange.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n12 + i += n13 + } + return i, nil +} +func (m *ResponseOp_ResponseTxn) MarshalTo(dAtA []byte) (int, error) { + i := 0 + if m.ResponseTxn != nil { + dAtA[i] = 0x22 + i++ + i = encodeVarintRpc(dAtA, i, uint64(m.ResponseTxn.Size())) + n14, err := m.ResponseTxn.MarshalTo(dAtA[i:]) + if err != nil { + return 0, err + } + i += n14 } return i, nil } @@ -5041,11 +5131,11 @@ func (m *Compare) MarshalTo(dAtA []byte) (int, error) { i += copy(dAtA[i:], m.Key) } if m.TargetUnion != nil { - nn13, err := m.TargetUnion.MarshalTo(dAtA[i:]) + nn15, err := m.TargetUnion.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += nn13 + i += nn15 } if len(m.RangeEnd) > 0 { dAtA[i] = 0x42 @@ -5160,11 +5250,11 @@ func (m *TxnResponse) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0xa i++ i = encodeVarintRpc(dAtA, i, uint64(m.Header.Size())) - n14, err := m.Header.MarshalTo(dAtA[i:]) + n16, err := m.Header.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n14 + i += n16 } if m.Succeeded { dAtA[i] = 0x10 @@ -5243,11 +5333,11 @@ func (m *CompactionResponse) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0xa i++ i = encodeVarintRpc(dAtA, i, uint64(m.Header.Size())) - n15, err := m.Header.MarshalTo(dAtA[i:]) + n17, err := m.Header.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n15 + i += n17 } return i, nil } @@ -5289,11 +5379,11 @@ func (m *HashResponse) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0xa i++ i = encodeVarintRpc(dAtA, i, uint64(m.Header.Size())) - n16, err := m.Header.MarshalTo(dAtA[i:]) + n18, err := m.Header.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n16 + i += n18 } if m.Hash != 0 { dAtA[i] = 0x10 @@ -5340,11 +5430,11 @@ func (m *SnapshotResponse) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0xa i++ i = encodeVarintRpc(dAtA, i, uint64(m.Header.Size())) - n17, err := m.Header.MarshalTo(dAtA[i:]) + n19, err := m.Header.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n17 + i += n19 } if m.RemainingBytes != 0 { dAtA[i] = 0x10 @@ -5376,11 +5466,11 @@ func (m *WatchRequest) MarshalTo(dAtA []byte) (int, error) { var l int _ = l if m.RequestUnion != nil { - nn18, err := m.RequestUnion.MarshalTo(dAtA[i:]) + nn20, err := m.RequestUnion.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += nn18 + i += nn20 } return i, nil } @@ -5391,11 +5481,11 @@ func (m *WatchRequest_CreateRequest) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0xa i++ i = encodeVarintRpc(dAtA, i, uint64(m.CreateRequest.Size())) - n19, err := m.CreateRequest.MarshalTo(dAtA[i:]) + n21, err := m.CreateRequest.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n19 + i += n21 } return i, nil } @@ -5405,11 +5495,11 @@ func (m *WatchRequest_CancelRequest) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0x12 i++ i = encodeVarintRpc(dAtA, i, uint64(m.CancelRequest.Size())) - n20, err := m.CancelRequest.MarshalTo(dAtA[i:]) + n22, err := m.CancelRequest.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n20 + i += n22 } return i, nil } @@ -5456,21 +5546,21 @@ func (m *WatchCreateRequest) MarshalTo(dAtA []byte) (int, error) { i++ } if len(m.Filters) > 0 { - dAtA22 := make([]byte, len(m.Filters)*10) - var j21 int + dAtA24 := make([]byte, len(m.Filters)*10) + var j23 int for _, num := range m.Filters { for num >= 1<<7 { - dAtA22[j21] = uint8(uint64(num)&0x7f | 0x80) + dAtA24[j23] = uint8(uint64(num)&0x7f | 0x80) num >>= 7 - j21++ + j23++ } - dAtA22[j21] = uint8(num) - j21++ + dAtA24[j23] = uint8(num) + j23++ } dAtA[i] = 0x2a i++ - i = encodeVarintRpc(dAtA, i, uint64(j21)) - i += copy(dAtA[i:], dAtA22[:j21]) + i = encodeVarintRpc(dAtA, i, uint64(j23)) + i += copy(dAtA[i:], dAtA24[:j23]) } if m.PrevKv { dAtA[i] = 0x30 @@ -5527,11 +5617,11 @@ func (m *WatchResponse) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0xa i++ i = encodeVarintRpc(dAtA, i, uint64(m.Header.Size())) - n23, err := m.Header.MarshalTo(dAtA[i:]) + n25, err := m.Header.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n23 + i += n25 } if m.WatchId != 0 { dAtA[i] = 0x10 @@ -5631,11 +5721,11 @@ func (m *LeaseGrantResponse) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0xa i++ i = encodeVarintRpc(dAtA, i, uint64(m.Header.Size())) - n24, err := m.Header.MarshalTo(dAtA[i:]) + n26, err := m.Header.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n24 + i += n26 } if m.ID != 0 { dAtA[i] = 0x10 @@ -5698,11 +5788,11 @@ func (m *LeaseRevokeResponse) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0xa i++ i = encodeVarintRpc(dAtA, i, uint64(m.Header.Size())) - n25, err := m.Header.MarshalTo(dAtA[i:]) + n27, err := m.Header.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n25 + i += n27 } return i, nil } @@ -5749,11 +5839,11 @@ func (m *LeaseKeepAliveResponse) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0xa i++ i = encodeVarintRpc(dAtA, i, uint64(m.Header.Size())) - n26, err := m.Header.MarshalTo(dAtA[i:]) + n28, err := m.Header.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n26 + i += n28 } if m.ID != 0 { dAtA[i] = 0x10 @@ -5820,11 +5910,11 @@ func (m *LeaseTimeToLiveResponse) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0xa i++ i = encodeVarintRpc(dAtA, i, uint64(m.Header.Size())) - n27, err := m.Header.MarshalTo(dAtA[i:]) + n29, err := m.Header.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n27 + i += n29 } if m.ID != 0 { dAtA[i] = 0x10 @@ -5963,21 +6053,21 @@ func (m *MemberAddResponse) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0xa i++ i = encodeVarintRpc(dAtA, i, uint64(m.Header.Size())) - n28, err := m.Header.MarshalTo(dAtA[i:]) + n30, err := m.Header.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n28 + i += n30 } if m.Member != nil { dAtA[i] = 0x12 i++ i = encodeVarintRpc(dAtA, i, uint64(m.Member.Size())) - n29, err := m.Member.MarshalTo(dAtA[i:]) + n31, err := m.Member.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n29 + i += n31 } if len(m.Members) > 0 { for _, msg := range m.Members { @@ -6036,11 +6126,11 @@ func (m *MemberRemoveResponse) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0xa i++ i = encodeVarintRpc(dAtA, i, uint64(m.Header.Size())) - n30, err := m.Header.MarshalTo(dAtA[i:]) + n32, err := m.Header.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n30 + i += n32 } if len(m.Members) > 0 { for _, msg := range m.Members { @@ -6114,11 +6204,11 @@ func (m *MemberUpdateResponse) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0xa i++ i = encodeVarintRpc(dAtA, i, uint64(m.Header.Size())) - n31, err := m.Header.MarshalTo(dAtA[i:]) + n33, err := m.Header.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n31 + i += n33 } if len(m.Members) > 0 { for _, msg := range m.Members { @@ -6172,11 +6262,11 @@ func (m *MemberListResponse) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0xa i++ i = encodeVarintRpc(dAtA, i, uint64(m.Header.Size())) - n32, err := m.Header.MarshalTo(dAtA[i:]) + n34, err := m.Header.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n32 + i += n34 } if len(m.Members) > 0 { for _, msg := range m.Members { @@ -6230,11 +6320,11 @@ func (m *DefragmentResponse) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0xa i++ i = encodeVarintRpc(dAtA, i, uint64(m.Header.Size())) - n33, err := m.Header.MarshalTo(dAtA[i:]) + n35, err := m.Header.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n33 + i += n35 } return i, nil } @@ -6319,11 +6409,11 @@ func (m *AlarmResponse) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0xa i++ i = encodeVarintRpc(dAtA, i, uint64(m.Header.Size())) - n34, err := m.Header.MarshalTo(dAtA[i:]) + n36, err := m.Header.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n34 + i += n36 } if len(m.Alarms) > 0 { for _, msg := range m.Alarms { @@ -6377,11 +6467,11 @@ func (m *StatusResponse) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0xa i++ i = encodeVarintRpc(dAtA, i, uint64(m.Header.Size())) - n35, err := m.Header.MarshalTo(dAtA[i:]) + n37, err := m.Header.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n35 + i += n37 } if len(m.Version) > 0 { dAtA[i] = 0x12 @@ -6779,11 +6869,11 @@ func (m *AuthRoleGrantPermissionRequest) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0x12 i++ i = encodeVarintRpc(dAtA, i, uint64(m.Perm.Size())) - n36, err := m.Perm.MarshalTo(dAtA[i:]) + n38, err := m.Perm.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n36 + i += n38 } return i, nil } @@ -6843,11 +6933,11 @@ func (m *AuthEnableResponse) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0xa i++ i = encodeVarintRpc(dAtA, i, uint64(m.Header.Size())) - n37, err := m.Header.MarshalTo(dAtA[i:]) + n39, err := m.Header.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n37 + i += n39 } return i, nil } @@ -6871,11 +6961,11 @@ func (m *AuthDisableResponse) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0xa i++ i = encodeVarintRpc(dAtA, i, uint64(m.Header.Size())) - n38, err := m.Header.MarshalTo(dAtA[i:]) + n40, err := m.Header.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n38 + i += n40 } return i, nil } @@ -6899,11 +6989,11 @@ func (m *AuthenticateResponse) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0xa i++ i = encodeVarintRpc(dAtA, i, uint64(m.Header.Size())) - n39, err := m.Header.MarshalTo(dAtA[i:]) + n41, err := m.Header.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n39 + i += n41 } if len(m.Token) > 0 { dAtA[i] = 0x12 @@ -6933,11 +7023,11 @@ func (m *AuthUserAddResponse) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0xa i++ i = encodeVarintRpc(dAtA, i, uint64(m.Header.Size())) - n40, err := m.Header.MarshalTo(dAtA[i:]) + n42, err := m.Header.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n40 + i += n42 } return i, nil } @@ -6961,11 +7051,11 @@ func (m *AuthUserGetResponse) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0xa i++ i = encodeVarintRpc(dAtA, i, uint64(m.Header.Size())) - n41, err := m.Header.MarshalTo(dAtA[i:]) + n43, err := m.Header.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n41 + i += n43 } if len(m.Roles) > 0 { for _, s := range m.Roles { @@ -7004,11 +7094,11 @@ func (m *AuthUserDeleteResponse) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0xa i++ i = encodeVarintRpc(dAtA, i, uint64(m.Header.Size())) - n42, err := m.Header.MarshalTo(dAtA[i:]) + n44, err := m.Header.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n42 + i += n44 } return i, nil } @@ -7032,11 +7122,11 @@ func (m *AuthUserChangePasswordResponse) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0xa i++ i = encodeVarintRpc(dAtA, i, uint64(m.Header.Size())) - n43, err := m.Header.MarshalTo(dAtA[i:]) + n45, err := m.Header.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n43 + i += n45 } return i, nil } @@ -7060,11 +7150,11 @@ func (m *AuthUserGrantRoleResponse) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0xa i++ i = encodeVarintRpc(dAtA, i, uint64(m.Header.Size())) - n44, err := m.Header.MarshalTo(dAtA[i:]) + n46, err := m.Header.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n44 + i += n46 } return i, nil } @@ -7088,11 +7178,11 @@ func (m *AuthUserRevokeRoleResponse) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0xa i++ i = encodeVarintRpc(dAtA, i, uint64(m.Header.Size())) - n45, err := m.Header.MarshalTo(dAtA[i:]) + n47, err := m.Header.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n45 + i += n47 } return i, nil } @@ -7116,11 +7206,11 @@ func (m *AuthRoleAddResponse) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0xa i++ i = encodeVarintRpc(dAtA, i, uint64(m.Header.Size())) - n46, err := m.Header.MarshalTo(dAtA[i:]) + n48, err := m.Header.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n46 + i += n48 } return i, nil } @@ -7144,11 +7234,11 @@ func (m *AuthRoleGetResponse) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0xa i++ i = encodeVarintRpc(dAtA, i, uint64(m.Header.Size())) - n47, err := m.Header.MarshalTo(dAtA[i:]) + n49, err := m.Header.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n47 + i += n49 } if len(m.Perm) > 0 { for _, msg := range m.Perm { @@ -7184,11 +7274,11 @@ func (m *AuthRoleListResponse) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0xa i++ i = encodeVarintRpc(dAtA, i, uint64(m.Header.Size())) - n48, err := m.Header.MarshalTo(dAtA[i:]) + n50, err := m.Header.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n48 + i += n50 } if len(m.Roles) > 0 { for _, s := range m.Roles { @@ -7227,11 +7317,11 @@ func (m *AuthUserListResponse) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0xa i++ i = encodeVarintRpc(dAtA, i, uint64(m.Header.Size())) - n49, err := m.Header.MarshalTo(dAtA[i:]) + n51, err := m.Header.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n49 + i += n51 } if len(m.Users) > 0 { for _, s := range m.Users { @@ -7270,11 +7360,11 @@ func (m *AuthRoleDeleteResponse) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0xa i++ i = encodeVarintRpc(dAtA, i, uint64(m.Header.Size())) - n50, err := m.Header.MarshalTo(dAtA[i:]) + n52, err := m.Header.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n50 + i += n52 } return i, nil } @@ -7298,11 +7388,11 @@ func (m *AuthRoleGrantPermissionResponse) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0xa i++ i = encodeVarintRpc(dAtA, i, uint64(m.Header.Size())) - n51, err := m.Header.MarshalTo(dAtA[i:]) + n53, err := m.Header.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n51 + i += n53 } return i, nil } @@ -7326,11 +7416,11 @@ func (m *AuthRoleRevokePermissionResponse) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0xa i++ i = encodeVarintRpc(dAtA, i, uint64(m.Header.Size())) - n52, err := m.Header.MarshalTo(dAtA[i:]) + n54, err := m.Header.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n52 + i += n54 } return i, nil } @@ -7561,6 +7651,15 @@ func (m *RequestOp_RequestDeleteRange) Size() (n int) { } return n } +func (m *RequestOp_RequestTxn) Size() (n int) { + var l int + _ = l + if m.RequestTxn != nil { + l = m.RequestTxn.Size() + n += 1 + l + sovRpc(uint64(l)) + } + return n +} func (m *ResponseOp) Size() (n int) { var l int _ = l @@ -7597,6 +7696,15 @@ func (m *ResponseOp_ResponseDeleteRange) Size() (n int) { } return n } +func (m *ResponseOp_ResponseTxn) Size() (n int) { + var l int + _ = l + if m.ResponseTxn != nil { + l = m.ResponseTxn.Size() + n += 1 + l + sovRpc(uint64(l)) + } + return n +} func (m *Compare) Size() (n int) { var l int _ = l @@ -9868,6 +9976,38 @@ func (m *RequestOp) Unmarshal(dAtA []byte) error { } m.Request = &RequestOp_RequestDeleteRange{v} iNdEx = postIndex + case 4: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field RequestTxn", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowRpc + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= (int(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthRpc + } + postIndex := iNdEx + msglen + if postIndex > l { + return io.ErrUnexpectedEOF + } + v := &TxnRequest{} + if err := v.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + m.Request = &RequestOp_RequestTxn{v} + iNdEx = postIndex default: iNdEx = preIndex skippy, err := skipRpc(dAtA[iNdEx:]) @@ -10014,6 +10154,38 @@ func (m *ResponseOp) Unmarshal(dAtA []byte) error { } m.Response = &ResponseOp_ResponseDeleteRange{v} iNdEx = postIndex + case 4: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field ResponseTxn", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowRpc + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= (int(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthRpc + } + postIndex := iNdEx + msglen + if postIndex > l { + return io.ErrUnexpectedEOF + } + v := &TxnResponse{} + if err := v.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + m.Response = &ResponseOp_ResponseTxn{v} + iNdEx = postIndex default: iNdEx = preIndex skippy, err := skipRpc(dAtA[iNdEx:]) @@ -17122,222 +17294,223 @@ var ( func init() { proto.RegisterFile("rpc.proto", fileDescriptorRpc) } var fileDescriptorRpc = []byte{ - // 3459 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xbc, 0x3b, 0x5b, 0x6f, 0x1b, 0xc7, - 0xb9, 0x5a, 0x52, 0xbc, 0x7d, 0xbc, 0x88, 0x1e, 0xc9, 0x36, 0x45, 0xdb, 0xb2, 0x3c, 0xbe, 0xc9, - 0x76, 0x22, 0x25, 0x4a, 0xce, 0x79, 0xf0, 0x09, 0x82, 0x23, 0x4b, 0x8c, 0xa5, 0x48, 0x96, 0x9c, - 0x95, 0xec, 0xe4, 0x00, 0xc1, 0x21, 0x56, 0xe4, 0x98, 0x5a, 0x88, 0xdc, 0x65, 0x76, 0x97, 0xb4, - 0x94, 0x93, 0x03, 0x14, 0x69, 0x82, 0xa2, 0x05, 0xfa, 0xd2, 0x3c, 0xf4, 0xf6, 0x58, 0x14, 0x45, - 0x7f, 0x40, 0xdf, 0xfa, 0x5c, 0x14, 0x7d, 0x69, 0x81, 0xfe, 0x81, 0x22, 0xed, 0x63, 0xdf, 0xfb, - 0x54, 0xb4, 0x98, 0xdb, 0xee, 0xec, 0x72, 0x97, 0x52, 0xca, 0x26, 0x2f, 0xd6, 0xce, 0x37, 0xdf, - 0x7c, 0xb7, 0x99, 0xef, 0x32, 0xdf, 0xd0, 0x50, 0x70, 0xfa, 0xad, 0xe5, 0xbe, 0x63, 0x7b, 0x36, - 0x2a, 0x11, 0xaf, 0xd5, 0x76, 0x89, 0x33, 0x24, 0x4e, 0xff, 0xb0, 0x3e, 0xd7, 0xb1, 0x3b, 0x36, - 0x9b, 0x58, 0xa1, 0x5f, 0x1c, 0xa7, 0x3e, 0x4f, 0x71, 0x56, 0x7a, 0xc3, 0x56, 0x8b, 0xfd, 0xd3, - 0x3f, 0x5c, 0x39, 0x1e, 0x8a, 0xa9, 0x2b, 0x6c, 0xca, 0x18, 0x78, 0x47, 0xec, 0x9f, 0xfe, 0x21, - 0xfb, 0x23, 0x26, 0xaf, 0x76, 0x6c, 0xbb, 0xd3, 0x25, 0x2b, 0x46, 0xdf, 0x5c, 0x31, 0x2c, 0xcb, - 0xf6, 0x0c, 0xcf, 0xb4, 0x2d, 0x97, 0xcf, 0xe2, 0xcf, 0x35, 0xa8, 0xe8, 0xc4, 0xed, 0xdb, 0x96, - 0x4b, 0x36, 0x89, 0xd1, 0x26, 0x0e, 0xba, 0x06, 0xd0, 0xea, 0x0e, 0x5c, 0x8f, 0x38, 0x4d, 0xb3, - 0x5d, 0xd3, 0x16, 0xb5, 0xa5, 0x69, 0xbd, 0x20, 0x20, 0x5b, 0x6d, 0x74, 0x05, 0x0a, 0x3d, 0xd2, - 0x3b, 0xe4, 0xb3, 0x29, 0x36, 0x9b, 0xe7, 0x80, 0xad, 0x36, 0xaa, 0x43, 0xde, 0x21, 0x43, 0xd3, - 0x35, 0x6d, 0xab, 0x96, 0x5e, 0xd4, 0x96, 0xd2, 0xba, 0x3f, 0xa6, 0x0b, 0x1d, 0xe3, 0x85, 0xd7, - 0xf4, 0x88, 0xd3, 0xab, 0x4d, 0xf3, 0x85, 0x14, 0x70, 0x40, 0x9c, 0x1e, 0xfe, 0x2c, 0x03, 0x25, - 0xdd, 0xb0, 0x3a, 0x44, 0x27, 0x1f, 0x0d, 0x88, 0xeb, 0xa1, 0x2a, 0xa4, 0x8f, 0xc9, 0x29, 0x63, - 0x5f, 0xd2, 0xe9, 0x27, 0x5f, 0x6f, 0x75, 0x48, 0x93, 0x58, 0x9c, 0x71, 0x89, 0xae, 0xb7, 0x3a, - 0xa4, 0x61, 0xb5, 0xd1, 0x1c, 0x64, 0xba, 0x66, 0xcf, 0xf4, 0x04, 0x57, 0x3e, 0x08, 0x89, 0x33, - 0x1d, 0x11, 0x67, 0x1d, 0xc0, 0xb5, 0x1d, 0xaf, 0x69, 0x3b, 0x6d, 0xe2, 0xd4, 0x32, 0x8b, 0xda, - 0x52, 0x65, 0xf5, 0xd6, 0xb2, 0xba, 0x11, 0xcb, 0xaa, 0x40, 0xcb, 0xfb, 0xb6, 0xe3, 0xed, 0x51, - 0x5c, 0xbd, 0xe0, 0xca, 0x4f, 0xf4, 0x0e, 0x14, 0x19, 0x11, 0xcf, 0x70, 0x3a, 0xc4, 0xab, 0x65, - 0x19, 0x95, 0xdb, 0x67, 0x50, 0x39, 0x60, 0xc8, 0x3a, 0x63, 0xcf, 0xbf, 0x11, 0x86, 0x92, 0x4b, - 0x1c, 0xd3, 0xe8, 0x9a, 0x1f, 0x1b, 0x87, 0x5d, 0x52, 0xcb, 0x2d, 0x6a, 0x4b, 0x79, 0x3d, 0x04, - 0xa3, 0xfa, 0x1f, 0x93, 0x53, 0xb7, 0x69, 0x5b, 0xdd, 0xd3, 0x5a, 0x9e, 0x21, 0xe4, 0x29, 0x60, - 0xcf, 0xea, 0x9e, 0xb2, 0x4d, 0xb3, 0x07, 0x96, 0xc7, 0x67, 0x0b, 0x6c, 0xb6, 0xc0, 0x20, 0x6c, - 0x7a, 0x09, 0xaa, 0x3d, 0xd3, 0x6a, 0xf6, 0xec, 0x76, 0xd3, 0x37, 0x08, 0x30, 0x83, 0x54, 0x7a, - 0xa6, 0xf5, 0xc4, 0x6e, 0xeb, 0xd2, 0x2c, 0x14, 0xd3, 0x38, 0x09, 0x63, 0x16, 0x05, 0xa6, 0x71, - 0xa2, 0x62, 0x2e, 0xc3, 0x2c, 0xa5, 0xd9, 0x72, 0x88, 0xe1, 0x91, 0x00, 0xb9, 0xc4, 0x90, 0x2f, - 0xf4, 0x4c, 0x6b, 0x9d, 0xcd, 0x84, 0xf0, 0x8d, 0x93, 0x11, 0xfc, 0xb2, 0xc0, 0x37, 0x4e, 0xc2, - 0xf8, 0x78, 0x19, 0x0a, 0xbe, 0xcd, 0x51, 0x1e, 0xa6, 0x77, 0xf7, 0x76, 0x1b, 0xd5, 0x29, 0x04, - 0x90, 0x5d, 0xdb, 0x5f, 0x6f, 0xec, 0x6e, 0x54, 0x35, 0x54, 0x84, 0xdc, 0x46, 0x83, 0x0f, 0x52, - 0xf8, 0x11, 0x40, 0x60, 0x5d, 0x94, 0x83, 0xf4, 0x76, 0xe3, 0x7f, 0xaa, 0x53, 0x14, 0xe7, 0x79, - 0x43, 0xdf, 0xdf, 0xda, 0xdb, 0xad, 0x6a, 0x74, 0xf1, 0xba, 0xde, 0x58, 0x3b, 0x68, 0x54, 0x53, - 0x14, 0xe3, 0xc9, 0xde, 0x46, 0x35, 0x8d, 0x0a, 0x90, 0x79, 0xbe, 0xb6, 0xf3, 0xac, 0x51, 0x9d, - 0xc6, 0x5f, 0x68, 0x50, 0x16, 0xfb, 0xc5, 0x7d, 0x02, 0xbd, 0x09, 0xd9, 0x23, 0xe6, 0x17, 0xec, - 0x28, 0x16, 0x57, 0xaf, 0x46, 0x36, 0x37, 0xe4, 0x3b, 0xba, 0xc0, 0x45, 0x18, 0xd2, 0xc7, 0x43, - 0xb7, 0x96, 0x5a, 0x4c, 0x2f, 0x15, 0x57, 0xab, 0xcb, 0xdc, 0x61, 0x97, 0xb7, 0xc9, 0xe9, 0x73, - 0xa3, 0x3b, 0x20, 0x3a, 0x9d, 0x44, 0x08, 0xa6, 0x7b, 0xb6, 0x43, 0xd8, 0x89, 0xcd, 0xeb, 0xec, - 0x9b, 0x1e, 0x63, 0xb6, 0x69, 0xe2, 0xb4, 0xf2, 0x01, 0xfe, 0xa5, 0x06, 0xf0, 0x74, 0xe0, 0x25, - 0xbb, 0xc6, 0x1c, 0x64, 0x86, 0x94, 0xb0, 0x70, 0x0b, 0x3e, 0x60, 0x3e, 0x41, 0x0c, 0x97, 0xf8, - 0x3e, 0x41, 0x07, 0xe8, 0x32, 0xe4, 0xfa, 0x0e, 0x19, 0x36, 0x8f, 0x87, 0x8c, 0x49, 0x5e, 0xcf, - 0xd2, 0xe1, 0xf6, 0x10, 0xdd, 0x80, 0x92, 0xd9, 0xb1, 0x6c, 0x87, 0x34, 0x39, 0xad, 0x0c, 0x9b, - 0x2d, 0x72, 0x18, 0x93, 0x5b, 0x41, 0xe1, 0x84, 0xb3, 0x2a, 0xca, 0x0e, 0x05, 0x61, 0x0b, 0x8a, - 0x4c, 0xd4, 0x89, 0xcc, 0x77, 0x2f, 0x90, 0x31, 0xc5, 0x96, 0x8d, 0x9a, 0x50, 0x48, 0x8d, 0x3f, - 0x04, 0xb4, 0x41, 0xba, 0xc4, 0x23, 0x93, 0x44, 0x0f, 0xc5, 0x26, 0x69, 0xd5, 0x26, 0xf8, 0x07, - 0x1a, 0xcc, 0x86, 0xc8, 0x4f, 0xa4, 0x56, 0x0d, 0x72, 0x6d, 0x46, 0x8c, 0x4b, 0x90, 0xd6, 0xe5, - 0x10, 0x3d, 0x80, 0xbc, 0x10, 0xc0, 0xad, 0xa5, 0x13, 0x0e, 0x4d, 0x8e, 0xcb, 0xe4, 0xe2, 0xbf, - 0x6a, 0x50, 0x10, 0x8a, 0xee, 0xf5, 0xd1, 0x1a, 0x94, 0x1d, 0x3e, 0x68, 0x32, 0x7d, 0x84, 0x44, - 0xf5, 0xe4, 0x20, 0xb4, 0x39, 0xa5, 0x97, 0xc4, 0x12, 0x06, 0x46, 0xff, 0x05, 0x45, 0x49, 0xa2, - 0x3f, 0xf0, 0x84, 0xc9, 0x6b, 0x61, 0x02, 0xc1, 0xf9, 0xdb, 0x9c, 0xd2, 0x41, 0xa0, 0x3f, 0x1d, - 0x78, 0xe8, 0x00, 0xe6, 0xe4, 0x62, 0xae, 0x8d, 0x10, 0x23, 0xcd, 0xa8, 0x2c, 0x86, 0xa9, 0x8c, - 0x6e, 0xd5, 0xe6, 0x94, 0x8e, 0xc4, 0x7a, 0x65, 0xf2, 0x51, 0x01, 0x72, 0x02, 0x8a, 0xff, 0xa6, - 0x01, 0x48, 0x83, 0xee, 0xf5, 0xd1, 0x06, 0x54, 0x1c, 0x31, 0x0a, 0x29, 0x7c, 0x25, 0x56, 0x61, - 0xb1, 0x0f, 0x53, 0x7a, 0x59, 0x2e, 0xe2, 0x2a, 0xbf, 0x0d, 0x25, 0x9f, 0x4a, 0xa0, 0xf3, 0x7c, - 0x8c, 0xce, 0x3e, 0x85, 0xa2, 0x5c, 0x40, 0xb5, 0x7e, 0x1f, 0x2e, 0xfa, 0xeb, 0x63, 0xd4, 0xbe, - 0x31, 0x46, 0x6d, 0x9f, 0xe0, 0xac, 0xa4, 0xa0, 0x2a, 0x0e, 0x34, 0x65, 0x71, 0x30, 0xfe, 0x4d, - 0x1a, 0x72, 0xeb, 0x76, 0xaf, 0x6f, 0x38, 0x74, 0x8f, 0xb2, 0x0e, 0x71, 0x07, 0x5d, 0x8f, 0xa9, - 0x5b, 0x59, 0xbd, 0x19, 0xe6, 0x20, 0xd0, 0xe4, 0x5f, 0x9d, 0xa1, 0xea, 0x62, 0x09, 0x5d, 0x2c, - 0x32, 0x54, 0xea, 0x1c, 0x8b, 0x45, 0x7e, 0x12, 0x4b, 0xa4, 0x2f, 0xa5, 0x03, 0x5f, 0xaa, 0x43, - 0x6e, 0x48, 0x9c, 0x20, 0xab, 0x6e, 0x4e, 0xe9, 0x12, 0x80, 0xee, 0xc1, 0x4c, 0x34, 0xc2, 0x67, - 0x04, 0x4e, 0xa5, 0x15, 0x4e, 0x08, 0x37, 0xa1, 0x14, 0x4a, 0x33, 0x59, 0x81, 0x57, 0xec, 0x29, - 0x59, 0xe6, 0x92, 0x0c, 0x6d, 0x34, 0x25, 0x96, 0x36, 0xa7, 0x64, 0x70, 0x0b, 0xf9, 0x73, 0x3e, - 0xec, 0xcf, 0xf8, 0xbf, 0xa1, 0x1c, 0x32, 0x04, 0x0d, 0xf1, 0x8d, 0xf7, 0x9e, 0xad, 0xed, 0xf0, - 0x7c, 0xf0, 0x98, 0xa5, 0x00, 0xbd, 0xaa, 0xd1, 0xb4, 0xb2, 0xd3, 0xd8, 0xdf, 0xaf, 0xa6, 0x50, - 0x19, 0x0a, 0xbb, 0x7b, 0x07, 0x4d, 0x8e, 0x95, 0xc6, 0x6f, 0xf9, 0x14, 0x44, 0x3e, 0x51, 0xd2, - 0xc8, 0x94, 0x92, 0x46, 0x34, 0x99, 0x46, 0x52, 0x41, 0x1a, 0x49, 0x3f, 0xaa, 0x40, 0x89, 0x1b, - 0xaf, 0x39, 0xb0, 0x68, 0x2a, 0xfb, 0x99, 0x06, 0x70, 0x70, 0x62, 0xc9, 0xe8, 0xb4, 0x02, 0xb9, - 0x16, 0x27, 0x5e, 0xd3, 0x98, 0xb3, 0x5f, 0x8c, 0xdd, 0x0f, 0x5d, 0x62, 0xa1, 0xd7, 0x21, 0xe7, - 0x0e, 0x5a, 0x2d, 0xe2, 0xca, 0x94, 0x72, 0x39, 0x1a, 0x6f, 0x44, 0x34, 0xd0, 0x25, 0x1e, 0x5d, - 0xf2, 0xc2, 0x30, 0xbb, 0x03, 0x96, 0x60, 0xc6, 0x2f, 0x11, 0x78, 0xf8, 0xc7, 0x1a, 0x14, 0x99, - 0x94, 0x13, 0x05, 0xb9, 0xab, 0x50, 0x60, 0x32, 0x90, 0xb6, 0x08, 0x73, 0x79, 0x3d, 0x00, 0xa0, - 0xff, 0x84, 0x82, 0x3c, 0xde, 0x32, 0xd2, 0xd5, 0xe2, 0xc9, 0xee, 0xf5, 0xf5, 0x00, 0x15, 0x6f, - 0xc3, 0x05, 0x66, 0x95, 0x16, 0x2d, 0x5e, 0xa5, 0x1d, 0xd5, 0xf2, 0x4e, 0x8b, 0x94, 0x77, 0x75, - 0xc8, 0xf7, 0x8f, 0x4e, 0x5d, 0xb3, 0x65, 0x74, 0x85, 0x14, 0xfe, 0x18, 0xbf, 0x0b, 0x48, 0x25, - 0x36, 0x89, 0xba, 0xb8, 0x0c, 0xc5, 0x4d, 0xc3, 0x3d, 0x12, 0x22, 0xe1, 0x0f, 0xa0, 0xc4, 0x87, - 0x13, 0xd9, 0x10, 0xc1, 0xf4, 0x91, 0xe1, 0x1e, 0x31, 0xc1, 0xcb, 0x3a, 0xfb, 0xc6, 0x17, 0x60, - 0x66, 0xdf, 0x32, 0xfa, 0xee, 0x91, 0x2d, 0x03, 0x31, 0x2d, 0xde, 0xab, 0x01, 0x6c, 0x22, 0x8e, - 0x77, 0x61, 0xc6, 0x21, 0x3d, 0xc3, 0xb4, 0x4c, 0xab, 0xd3, 0x3c, 0x3c, 0xf5, 0x88, 0x2b, 0x6a, - 0xfb, 0x8a, 0x0f, 0x7e, 0x44, 0xa1, 0x54, 0xb4, 0xc3, 0xae, 0x7d, 0x28, 0xc2, 0x01, 0xfb, 0xc6, - 0xbf, 0xd2, 0xa0, 0xf4, 0xbe, 0xe1, 0xb5, 0xa4, 0x15, 0xd0, 0x16, 0x54, 0xfc, 0x20, 0xc0, 0x20, - 0x42, 0x96, 0x48, 0x36, 0x60, 0x6b, 0x64, 0xd5, 0x27, 0xb3, 0x41, 0xb9, 0xa5, 0x02, 0x18, 0x29, - 0xc3, 0x6a, 0x91, 0xae, 0x4f, 0x2a, 0x95, 0x4c, 0x8a, 0x21, 0xaa, 0xa4, 0x54, 0xc0, 0xa3, 0x99, - 0x20, 0x53, 0x72, 0xb7, 0xfc, 0x49, 0x0a, 0xd0, 0xa8, 0x0c, 0x5f, 0xb5, 0x78, 0xb8, 0x0d, 0x15, - 0xd7, 0x33, 0x1c, 0xaf, 0x19, 0xb9, 0xf9, 0x94, 0x19, 0xd4, 0x0f, 0x64, 0x77, 0x61, 0xa6, 0xef, - 0xd8, 0x1d, 0x87, 0xb8, 0x6e, 0xd3, 0xb2, 0x3d, 0xf3, 0xc5, 0xa9, 0xa8, 0xbf, 0x2a, 0x12, 0xbc, - 0xcb, 0xa0, 0xa8, 0x01, 0xb9, 0x17, 0x66, 0xd7, 0x23, 0x8e, 0x5b, 0xcb, 0x2c, 0xa6, 0x97, 0x2a, - 0xab, 0x0f, 0xce, 0xb2, 0xda, 0xf2, 0x3b, 0x0c, 0xff, 0xe0, 0xb4, 0x4f, 0x74, 0xb9, 0x56, 0xad, - 0x69, 0xb2, 0xa1, 0x9a, 0xe6, 0x36, 0x40, 0x80, 0x4f, 0xa3, 0xd6, 0xee, 0xde, 0xd3, 0x67, 0x07, - 0xd5, 0x29, 0x54, 0x82, 0xfc, 0xee, 0xde, 0x46, 0x63, 0xa7, 0x41, 0xe3, 0x1a, 0x5e, 0x91, 0xb6, - 0x51, 0x6d, 0x88, 0xe6, 0x21, 0xff, 0x92, 0x42, 0xe5, 0xd5, 0x30, 0xad, 0xe7, 0xd8, 0x78, 0xab, - 0x8d, 0xbf, 0x9f, 0x82, 0xb2, 0x38, 0x05, 0x13, 0x1d, 0x45, 0x95, 0x45, 0x2a, 0xc4, 0x82, 0x16, - 0x50, 0xfc, 0x74, 0xb4, 0x45, 0x9d, 0x26, 0x87, 0xd4, 0xdd, 0xf9, 0x66, 0x93, 0xb6, 0x30, 0xab, - 0x3f, 0x46, 0xf7, 0xa0, 0xda, 0xe2, 0xee, 0x1e, 0xc9, 0x49, 0xfa, 0x8c, 0x80, 0x2b, 0x29, 0xa9, - 0xec, 0x9f, 0x36, 0xc3, 0x15, 0x39, 0xa9, 0xa0, 0x97, 0xe4, 0x41, 0xa2, 0x30, 0x74, 0x1b, 0xb2, - 0x64, 0x48, 0x2c, 0xcf, 0xad, 0x15, 0x59, 0x00, 0x2b, 0xcb, 0x52, 0xad, 0x41, 0xa1, 0xba, 0x98, - 0xc4, 0xff, 0x01, 0x17, 0x58, 0x49, 0xfc, 0xd8, 0x31, 0x2c, 0xb5, 0x76, 0x3f, 0x38, 0xd8, 0x11, - 0xa6, 0xa3, 0x9f, 0xa8, 0x02, 0xa9, 0xad, 0x0d, 0xa1, 0x68, 0x6a, 0x6b, 0x03, 0x7f, 0xaa, 0x01, - 0x52, 0xd7, 0x4d, 0x64, 0xcb, 0x08, 0x71, 0xc9, 0x3e, 0x1d, 0xb0, 0x9f, 0x83, 0x0c, 0x71, 0x1c, - 0xdb, 0x61, 0x56, 0x2b, 0xe8, 0x7c, 0x80, 0x6f, 0x09, 0x19, 0x74, 0x32, 0xb4, 0x8f, 0x7d, 0xc7, - 0xe0, 0xd4, 0x34, 0x5f, 0xd4, 0x6d, 0x98, 0x0d, 0x61, 0x4d, 0x14, 0x48, 0xef, 0xc2, 0x45, 0x46, - 0x6c, 0x9b, 0x90, 0xfe, 0x5a, 0xd7, 0x1c, 0x26, 0x72, 0xed, 0xc3, 0xa5, 0x28, 0xe2, 0xd7, 0x6b, - 0x23, 0xfc, 0x96, 0xe0, 0x78, 0x60, 0xf6, 0xc8, 0x81, 0xbd, 0x93, 0x2c, 0x1b, 0x8d, 0x8e, 0xf4, - 0x4a, 0x2e, 0x32, 0x0e, 0xfb, 0xc6, 0x3f, 0xd7, 0xe0, 0xf2, 0xc8, 0xf2, 0xaf, 0x79, 0x57, 0x17, - 0x00, 0x3a, 0xf4, 0xf8, 0x90, 0x36, 0x9d, 0xe0, 0x97, 0x49, 0x05, 0xe2, 0xcb, 0x49, 0x03, 0x4c, - 0x49, 0xc8, 0x79, 0x04, 0xd9, 0x27, 0xac, 0x8f, 0xa3, 0x68, 0x35, 0x2d, 0xb5, 0xb2, 0x8c, 0x1e, - 0xbf, 0x5d, 0x16, 0x74, 0xf6, 0xcd, 0xf2, 0x2b, 0x21, 0xce, 0x33, 0x7d, 0x87, 0xe7, 0xf1, 0x82, - 0xee, 0x8f, 0x29, 0xf7, 0x56, 0xd7, 0x24, 0x96, 0xc7, 0x66, 0xa7, 0xd9, 0xac, 0x02, 0xc1, 0xcb, - 0x50, 0xe5, 0x9c, 0xd6, 0xda, 0x6d, 0x25, 0x97, 0xfb, 0xf4, 0xb4, 0x30, 0x3d, 0xfc, 0x0b, 0x0d, - 0x2e, 0x28, 0x0b, 0x26, 0xb2, 0xdd, 0x2b, 0x90, 0xe5, 0xdd, 0x2a, 0x91, 0x47, 0xe6, 0xc2, 0xab, - 0x38, 0x1b, 0x5d, 0xe0, 0xa0, 0x65, 0xc8, 0xf1, 0x2f, 0x59, 0xac, 0xc4, 0xa3, 0x4b, 0x24, 0x7c, - 0x1b, 0x66, 0x05, 0x88, 0xf4, 0xec, 0xb8, 0x63, 0xc2, 0x0c, 0x8a, 0x3f, 0x81, 0xb9, 0x30, 0xda, - 0x44, 0x2a, 0x29, 0x42, 0xa6, 0xce, 0x23, 0xe4, 0x9a, 0x14, 0xf2, 0x59, 0xbf, 0xad, 0xa4, 0xbd, - 0xe8, 0xae, 0xab, 0x3b, 0x92, 0x8a, 0xec, 0x88, 0xaf, 0x80, 0x24, 0xf1, 0x8d, 0x2a, 0x30, 0x2b, - 0x8f, 0xc3, 0x8e, 0xe9, 0xfa, 0xc5, 0xd0, 0xc7, 0x80, 0x54, 0xe0, 0x37, 0x2d, 0xd0, 0x06, 0x79, - 0xe1, 0x18, 0x9d, 0x1e, 0xf1, 0x43, 0x3d, 0xad, 0x32, 0x55, 0xe0, 0x44, 0xc1, 0xf1, 0xf7, 0x1a, - 0x94, 0xd6, 0xba, 0x86, 0xd3, 0x93, 0x9b, 0xf5, 0x36, 0x64, 0x79, 0xf9, 0x2a, 0xae, 0x83, 0x77, - 0xc2, 0x64, 0x54, 0x5c, 0x3e, 0x58, 0xe3, 0xc5, 0xae, 0x58, 0x45, 0x37, 0x57, 0x34, 0x6d, 0x37, - 0x22, 0x4d, 0xdc, 0x0d, 0xf4, 0x2a, 0x64, 0x0c, 0xba, 0x84, 0x05, 0x94, 0x4a, 0xf4, 0xe2, 0xc0, - 0xa8, 0xb1, 0x52, 0x83, 0x63, 0xe1, 0x37, 0xa1, 0xa8, 0x70, 0xa0, 0xf7, 0xa1, 0xc7, 0x0d, 0x51, - 0x4e, 0xac, 0xad, 0x1f, 0x6c, 0x3d, 0xe7, 0xd7, 0xa4, 0x0a, 0xc0, 0x46, 0xc3, 0x1f, 0xa7, 0xf0, - 0x07, 0x62, 0x95, 0x08, 0x39, 0xaa, 0x3c, 0x5a, 0x92, 0x3c, 0xa9, 0x73, 0xc9, 0x73, 0x02, 0x65, - 0xa1, 0xfe, 0x44, 0x67, 0xe0, 0x75, 0xc8, 0x32, 0x7a, 0xf2, 0x08, 0xcc, 0xc7, 0xb0, 0x95, 0xd1, - 0x82, 0x23, 0xe2, 0x19, 0x28, 0xef, 0x7b, 0x86, 0x37, 0x70, 0xe5, 0x11, 0xf8, 0x9d, 0x06, 0x15, - 0x09, 0x99, 0xb4, 0x73, 0x24, 0x6f, 0xdc, 0x3c, 0x08, 0xfb, 0xf7, 0xed, 0x4b, 0x90, 0x6d, 0x1f, - 0xee, 0x9b, 0x1f, 0xcb, 0x2e, 0x9f, 0x18, 0x51, 0x78, 0x97, 0xf3, 0xe1, 0xad, 0x76, 0x31, 0xa2, - 0xd7, 0x33, 0xc7, 0x78, 0xe1, 0x6d, 0x59, 0x6d, 0x72, 0xc2, 0xaa, 0xa0, 0x69, 0x3d, 0x00, 0xb0, - 0x1b, 0x95, 0x68, 0xc9, 0xb3, 0xd2, 0x47, 0x6d, 0xd1, 0xcf, 0xc2, 0x85, 0xb5, 0x81, 0x77, 0xd4, - 0xb0, 0x8c, 0xc3, 0xae, 0x0c, 0x1a, 0x78, 0x0e, 0x10, 0x05, 0x6e, 0x98, 0xae, 0x0a, 0x6d, 0xc0, - 0x2c, 0x85, 0x12, 0xcb, 0x33, 0x5b, 0x4a, 0x84, 0x91, 0x79, 0x44, 0x8b, 0xe4, 0x11, 0xc3, 0x75, - 0x5f, 0xda, 0x4e, 0x5b, 0xa8, 0xe6, 0x8f, 0xf1, 0x06, 0x27, 0xfe, 0xcc, 0x0d, 0x65, 0x8a, 0xaf, - 0x4a, 0x65, 0x29, 0xa0, 0xf2, 0x98, 0x78, 0x63, 0xa8, 0xe0, 0x07, 0x70, 0x51, 0x62, 0x8a, 0x96, - 0xcc, 0x18, 0xe4, 0x3d, 0xb8, 0x26, 0x91, 0xd7, 0x8f, 0xe8, 0x5d, 0xe0, 0xa9, 0x60, 0xf8, 0xaf, - 0xca, 0xf9, 0x08, 0x6a, 0xbe, 0x9c, 0xac, 0xf4, 0xb3, 0xbb, 0xaa, 0x00, 0x03, 0x57, 0x9c, 0x99, - 0x82, 0xce, 0xbe, 0x29, 0xcc, 0xb1, 0xbb, 0x7e, 0x56, 0xa6, 0xdf, 0x78, 0x1d, 0xe6, 0x25, 0x0d, - 0x51, 0x94, 0x85, 0x89, 0x8c, 0x08, 0x14, 0x47, 0x44, 0x18, 0x8c, 0x2e, 0x1d, 0x6f, 0x76, 0x15, - 0x33, 0x6c, 0x5a, 0x46, 0x53, 0x53, 0x68, 0x5e, 0xe4, 0x27, 0x82, 0x0a, 0xa6, 0x06, 0x6d, 0x01, - 0xa6, 0x04, 0x54, 0xb0, 0xd8, 0x08, 0x0a, 0x1e, 0xd9, 0x88, 0x11, 0xd2, 0x1f, 0xc2, 0x82, 0x2f, - 0x04, 0xb5, 0xdb, 0x53, 0xe2, 0xf4, 0x4c, 0xd7, 0x55, 0xfa, 0x04, 0x71, 0x8a, 0xdf, 0x81, 0xe9, - 0x3e, 0x11, 0x31, 0xa5, 0xb8, 0x8a, 0x96, 0xf9, 0xc3, 0xd9, 0xb2, 0xb2, 0x98, 0xcd, 0xe3, 0x36, - 0x5c, 0x97, 0xd4, 0xb9, 0x45, 0x63, 0xc9, 0x47, 0x85, 0x92, 0x77, 0x48, 0x6e, 0xd6, 0xd1, 0x3b, - 0x64, 0x9a, 0xef, 0xbd, 0xdf, 0xb0, 0x7a, 0x97, 0x1b, 0x52, 0xfa, 0xd6, 0x44, 0xb9, 0x62, 0x9b, - 0xdb, 0xd4, 0x77, 0xc9, 0x89, 0x88, 0x1d, 0xc2, 0x5c, 0xd8, 0x93, 0x27, 0x0a, 0x63, 0x73, 0x90, - 0xf1, 0xec, 0x63, 0x22, 0x83, 0x18, 0x1f, 0x48, 0x81, 0x7d, 0x37, 0x9f, 0x48, 0x60, 0x23, 0x20, - 0xc6, 0x8e, 0xe4, 0xa4, 0xf2, 0xd2, 0xdd, 0x94, 0xf5, 0x0f, 0x1f, 0xe0, 0x5d, 0xb8, 0x14, 0x0d, - 0x13, 0x13, 0x89, 0xfc, 0x9c, 0x1f, 0xe0, 0xb8, 0x48, 0x32, 0x11, 0xdd, 0xf7, 0x82, 0x60, 0xa0, - 0x04, 0x94, 0x89, 0x48, 0xea, 0x50, 0x8f, 0x8b, 0x2f, 0xff, 0x8e, 0xf3, 0xea, 0x87, 0x9b, 0x89, - 0x88, 0xb9, 0x01, 0xb1, 0xc9, 0xb7, 0x3f, 0x88, 0x11, 0xe9, 0xb1, 0x31, 0x42, 0x38, 0x49, 0x10, - 0xc5, 0xbe, 0x86, 0x43, 0x27, 0x78, 0x04, 0x01, 0x74, 0x52, 0x1e, 0x34, 0x87, 0xf8, 0x3c, 0xd8, - 0x40, 0x1e, 0x6c, 0x35, 0xec, 0x4e, 0xb4, 0x19, 0xef, 0x07, 0xb1, 0x73, 0x24, 0x32, 0x4f, 0x44, - 0xf8, 0x03, 0x58, 0x4c, 0x0e, 0xca, 0x93, 0x50, 0xbe, 0x8f, 0xa1, 0xe0, 0x17, 0x94, 0xca, 0xa3, - 0x73, 0x11, 0x72, 0xbb, 0x7b, 0xfb, 0x4f, 0xd7, 0xd6, 0x1b, 0x55, 0x6d, 0xf5, 0xef, 0x69, 0x48, - 0x6d, 0x3f, 0x47, 0xff, 0x0b, 0x19, 0xfe, 0x96, 0x34, 0xe6, 0xa9, 0xad, 0x3e, 0xee, 0x55, 0x0a, - 0x5f, 0xfd, 0xf4, 0x8f, 0x7f, 0xf9, 0x22, 0x75, 0x09, 0x5f, 0x58, 0x19, 0xbe, 0x61, 0x74, 0xfb, - 0x47, 0xc6, 0xca, 0xf1, 0x70, 0x85, 0xe5, 0x84, 0x87, 0xda, 0x7d, 0xf4, 0x1c, 0xd2, 0x4f, 0x07, - 0x1e, 0x4a, 0x7c, 0x87, 0xab, 0x27, 0xbf, 0x56, 0xe1, 0x3a, 0xa3, 0x3c, 0x87, 0x67, 0x54, 0xca, - 0xfd, 0x81, 0x47, 0xe9, 0x0e, 0xa1, 0xa8, 0x3c, 0x38, 0xa1, 0x33, 0x5f, 0xe8, 0xea, 0x67, 0x3f, - 0x66, 0x61, 0xcc, 0xf8, 0x5d, 0xc5, 0x97, 0x55, 0x7e, 0xfc, 0x5d, 0x4c, 0xd5, 0xe7, 0xe0, 0xc4, - 0x8a, 0xea, 0x13, 0x3c, 0x8b, 0x44, 0xf5, 0x51, 0x9e, 0x22, 0xe2, 0xf5, 0xf1, 0x4e, 0x2c, 0x4a, - 0xd7, 0x16, 0x8f, 0x64, 0x2d, 0x0f, 0x5d, 0x8f, 0x79, 0x47, 0x51, 0x5f, 0x0c, 0xea, 0x8b, 0xc9, - 0x08, 0x82, 0xd3, 0x0d, 0xc6, 0xe9, 0x0a, 0xbe, 0xa4, 0x72, 0x6a, 0xf9, 0x78, 0x0f, 0xb5, 0xfb, - 0xab, 0x47, 0x90, 0x61, 0x7d, 0x4e, 0xd4, 0x94, 0x1f, 0xf5, 0x98, 0x0e, 0x6d, 0xc2, 0x09, 0x08, - 0x75, 0x48, 0xf1, 0x3c, 0xe3, 0x36, 0x8b, 0x2b, 0x3e, 0x37, 0xd6, 0xea, 0x7c, 0xa8, 0xdd, 0x5f, - 0xd2, 0x5e, 0xd3, 0x56, 0xbf, 0x3d, 0x0d, 0x19, 0xd6, 0x3a, 0x42, 0x7d, 0x80, 0xa0, 0x29, 0x18, - 0xd5, 0x73, 0xa4, 0xcd, 0x18, 0xd5, 0x73, 0xb4, 0x9f, 0x88, 0xaf, 0x33, 0xce, 0xf3, 0x78, 0xce, - 0xe7, 0xcc, 0x9e, 0xf4, 0x57, 0x58, 0x93, 0x88, 0x9a, 0xf5, 0x25, 0x14, 0x95, 0xe6, 0x1e, 0x8a, - 0xa3, 0x18, 0xea, 0x0e, 0x46, 0x8f, 0x49, 0x4c, 0x67, 0x10, 0xdf, 0x64, 0x4c, 0xaf, 0xe1, 0x9a, - 0x6a, 0x5c, 0xce, 0xd7, 0x61, 0x98, 0x94, 0xf1, 0x67, 0x1a, 0x54, 0xc2, 0x0d, 0x3e, 0x74, 0x33, - 0x86, 0x74, 0xb4, 0x4f, 0x58, 0xbf, 0x35, 0x1e, 0x29, 0x51, 0x04, 0xce, 0xff, 0x98, 0x90, 0xbe, - 0x41, 0x31, 0x85, 0xed, 0xd1, 0x77, 0x34, 0x98, 0x89, 0xb4, 0xed, 0x50, 0x1c, 0x8b, 0x91, 0xa6, - 0x60, 0xfd, 0xf6, 0x19, 0x58, 0x42, 0x92, 0xbb, 0x4c, 0x92, 0x1b, 0xf8, 0xea, 0xa8, 0x31, 0x3c, - 0xb3, 0x47, 0x3c, 0x5b, 0x48, 0xb3, 0xfa, 0x8f, 0x34, 0xe4, 0xd6, 0xf9, 0xef, 0xaf, 0x90, 0x07, - 0x05, 0xbf, 0x13, 0x86, 0x16, 0xe2, 0xba, 0x12, 0x41, 0xc9, 0x5e, 0xbf, 0x9e, 0x38, 0x2f, 0x44, - 0xb8, 0xc3, 0x44, 0x58, 0xc4, 0x57, 0x7c, 0x11, 0xc4, 0xef, 0xbc, 0x56, 0xf8, 0xe5, 0x7b, 0xc5, - 0x68, 0xb7, 0xe9, 0x96, 0x7c, 0x4b, 0x83, 0x92, 0xda, 0xb0, 0x42, 0x37, 0x62, 0xfb, 0x21, 0x6a, - 0xcf, 0xab, 0x8e, 0xc7, 0xa1, 0x08, 0xfe, 0xf7, 0x18, 0xff, 0x9b, 0x78, 0x21, 0x89, 0xbf, 0xc3, - 0xf0, 0xc3, 0x22, 0xf0, 0x96, 0x53, 0xbc, 0x08, 0xa1, 0x8e, 0x56, 0xbc, 0x08, 0xe1, 0x8e, 0xd5, - 0xd9, 0x22, 0x0c, 0x18, 0x3e, 0x15, 0xe1, 0x04, 0x20, 0xe8, 0x30, 0xa1, 0x58, 0xe3, 0x2a, 0x97, - 0x98, 0xa8, 0x0f, 0x8e, 0x36, 0xa7, 0x62, 0x4e, 0x40, 0x84, 0x77, 0xd7, 0x74, 0xa9, 0x2f, 0xae, - 0xfe, 0x7a, 0x1a, 0x8a, 0x4f, 0x0c, 0xd3, 0xf2, 0x88, 0x65, 0x58, 0x2d, 0x82, 0x3a, 0x90, 0x61, - 0x59, 0x2a, 0x1a, 0x78, 0xd4, 0xb6, 0x4f, 0x34, 0xf0, 0x84, 0x7a, 0x22, 0xf8, 0x36, 0x63, 0x7d, - 0x1d, 0xd7, 0x7d, 0xd6, 0xbd, 0x80, 0xfe, 0x0a, 0xeb, 0x67, 0x50, 0x95, 0x8f, 0x21, 0xcb, 0xfb, - 0x17, 0x28, 0x42, 0x2d, 0xd4, 0xe7, 0xa8, 0x5f, 0x8d, 0x9f, 0x4c, 0x3c, 0x65, 0x2a, 0x2f, 0x97, - 0x21, 0x53, 0x66, 0xff, 0x07, 0x10, 0x34, 0xcc, 0xa2, 0xf6, 0x1d, 0xe9, 0xaf, 0xd5, 0x17, 0x93, - 0x11, 0x04, 0xe3, 0xfb, 0x8c, 0xf1, 0x2d, 0x7c, 0x3d, 0x96, 0x71, 0xdb, 0x5f, 0x40, 0x99, 0xb7, - 0x60, 0x7a, 0xd3, 0x70, 0x8f, 0x50, 0x24, 0x09, 0x29, 0x6f, 0xbb, 0xf5, 0x7a, 0xdc, 0x94, 0x60, - 0x75, 0x8b, 0xb1, 0x5a, 0xc0, 0xf3, 0xb1, 0xac, 0x8e, 0x0c, 0x97, 0xc6, 0x74, 0x34, 0x80, 0xbc, - 0x7c, 0xaf, 0x45, 0xd7, 0x22, 0x36, 0x0b, 0xbf, 0xed, 0xd6, 0x17, 0x92, 0xa6, 0x05, 0xc3, 0x25, - 0xc6, 0x10, 0xe3, 0x6b, 0xf1, 0x46, 0x15, 0xe8, 0x0f, 0xb5, 0xfb, 0xaf, 0x69, 0xab, 0xdf, 0xab, - 0xc2, 0x34, 0xad, 0x97, 0x68, 0x16, 0x09, 0xae, 0x99, 0x51, 0x0b, 0x8f, 0x34, 0x77, 0xa2, 0x16, - 0x1e, 0xbd, 0xa1, 0xc6, 0x64, 0x11, 0xf6, 0x2b, 0x54, 0xc2, 0xb0, 0xa8, 0xc6, 0x1e, 0x14, 0x95, - 0xcb, 0x28, 0x8a, 0xa1, 0x18, 0x6e, 0x1d, 0x45, 0xb3, 0x48, 0xcc, 0x4d, 0x16, 0x2f, 0x32, 0xa6, - 0x75, 0x7c, 0x31, 0xcc, 0xb4, 0xcd, 0xd1, 0x28, 0xd7, 0x4f, 0xa0, 0xa4, 0xde, 0x5a, 0x51, 0x0c, - 0xd1, 0x48, 0x6f, 0x2a, 0x1a, 0x2b, 0xe2, 0x2e, 0xbd, 0x31, 0x4e, 0xe3, 0xff, 0xe6, 0x56, 0xe2, - 0x52, 0xee, 0x1f, 0x41, 0x4e, 0xdc, 0x65, 0xe3, 0xf4, 0x0d, 0x77, 0xb3, 0xe2, 0xf4, 0x8d, 0x5c, - 0x84, 0x63, 0x4a, 0x12, 0xc6, 0x96, 0xd6, 0xec, 0x32, 0x40, 0x0b, 0x96, 0x8f, 0x89, 0x97, 0xc4, - 0x32, 0xe8, 0xcf, 0x24, 0xb1, 0x54, 0xee, 0x4b, 0x63, 0x59, 0x76, 0x88, 0x27, 0xce, 0xb2, 0xbc, - 0x8c, 0xa0, 0x04, 0x8a, 0x6a, 0x34, 0xc4, 0xe3, 0x50, 0x12, 0xab, 0xc8, 0x80, 0xab, 0x08, 0x85, - 0xe8, 0xff, 0x01, 0x82, 0x8b, 0x77, 0xb4, 0x30, 0x88, 0xed, 0xde, 0x45, 0x0b, 0x83, 0xf8, 0xbb, - 0x7b, 0x8c, 0x07, 0x07, 0xcc, 0x79, 0x25, 0x4b, 0xd9, 0xff, 0x50, 0x03, 0x34, 0x7a, 0x51, 0x47, - 0x0f, 0xe2, 0x59, 0xc4, 0x36, 0x06, 0xeb, 0xaf, 0x9c, 0x0f, 0x39, 0x31, 0x7a, 0x06, 0x72, 0xb5, - 0xd8, 0x92, 0xfe, 0x4b, 0x2a, 0xd9, 0xe7, 0x1a, 0x94, 0x43, 0x57, 0x7d, 0x74, 0x27, 0x61, 0x9f, - 0x23, 0xcd, 0xc5, 0xfa, 0xdd, 0x33, 0xf1, 0x12, 0x6b, 0x27, 0xe5, 0x54, 0xc8, 0xba, 0xf1, 0xbb, - 0x1a, 0x54, 0xc2, 0xfd, 0x01, 0x94, 0xc0, 0x60, 0xa4, 0x43, 0x59, 0x5f, 0x3a, 0x1b, 0xf1, 0x1c, - 0xbb, 0x15, 0x94, 0x92, 0x1f, 0x41, 0x4e, 0xb4, 0x15, 0xe2, 0xdc, 0x22, 0xdc, 0xe0, 0x8c, 0x73, - 0x8b, 0x48, 0x4f, 0x22, 0xc9, 0x2d, 0xe8, 0x0d, 0x5d, 0xf1, 0x44, 0xd1, 0x7c, 0x48, 0x62, 0x39, - 0xde, 0x13, 0x23, 0x9d, 0x8b, 0xb1, 0x2c, 0x03, 0x4f, 0x94, 0xad, 0x07, 0x94, 0x40, 0xf1, 0x0c, - 0x4f, 0x8c, 0x76, 0x2e, 0x92, 0x3c, 0x91, 0x71, 0x55, 0x3c, 0x31, 0xe8, 0x14, 0xc4, 0x79, 0xe2, - 0x48, 0xfb, 0x36, 0xce, 0x13, 0x47, 0x9b, 0x0d, 0x49, 0x7b, 0xcb, 0x98, 0x87, 0x3c, 0x71, 0x36, - 0xa6, 0xb3, 0x80, 0x5e, 0x49, 0xb0, 0x69, 0x6c, 0x6b, 0xb8, 0xfe, 0xea, 0x39, 0xb1, 0xc7, 0x7b, - 0x00, 0xdf, 0x0d, 0xe9, 0x01, 0x3f, 0xd5, 0x60, 0x2e, 0xae, 0x35, 0x81, 0x12, 0x98, 0x25, 0xf4, - 0x95, 0xeb, 0xcb, 0xe7, 0x45, 0x3f, 0x87, 0xdd, 0x7c, 0x9f, 0x78, 0x54, 0xfd, 0xed, 0x97, 0x0b, - 0xda, 0x1f, 0xbe, 0x5c, 0xd0, 0xfe, 0xf4, 0xe5, 0x82, 0xf6, 0xa3, 0x3f, 0x2f, 0x4c, 0x1d, 0x66, - 0xd9, 0x7f, 0x05, 0x79, 0xe3, 0x9f, 0x01, 0x00, 0x00, 0xff, 0xff, 0xe5, 0x0a, 0xcf, 0x02, 0x91, - 0x32, 0x00, 0x00, + // 3487 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xbc, 0x5b, 0xdd, 0x6f, 0x1b, 0xc7, + 0xb5, 0xd7, 0x92, 0x12, 0x29, 0x1e, 0x7e, 0x88, 0x1e, 0xc9, 0x36, 0xb5, 0xb6, 0x65, 0x79, 0xfc, + 0x25, 0xdb, 0x89, 0x94, 0x28, 0xb9, 0xf7, 0xc1, 0x37, 0x08, 0xae, 0x2c, 0x31, 0x96, 0x22, 0x59, + 0x72, 0x56, 0xb2, 0x93, 0x0b, 0x04, 0x97, 0x58, 0x91, 0x63, 0x6a, 0x21, 0x72, 0x97, 0xd9, 0x5d, + 0xd2, 0x52, 0x6e, 0x2e, 0x70, 0x91, 0x9b, 0xa0, 0x68, 0x81, 0xbe, 0x34, 0x0f, 0xfd, 0x7a, 0x2c, + 0x8a, 0x22, 0x7f, 0x40, 0xd1, 0x97, 0x3e, 0x17, 0x45, 0x5f, 0x5a, 0xa0, 0xff, 0x40, 0x91, 0xf6, + 0xdf, 0x28, 0x5a, 0xcc, 0xd7, 0xee, 0xec, 0x72, 0x97, 0x52, 0xc2, 0x26, 0x2f, 0xd6, 0xce, 0x99, + 0x33, 0xe7, 0x77, 0xe6, 0xcc, 0x9c, 0x73, 0x66, 0xce, 0xd0, 0x50, 0x70, 0x7b, 0xcd, 0xe5, 0x9e, + 0xeb, 0xf8, 0x0e, 0x2a, 0x11, 0xbf, 0xd9, 0xf2, 0x88, 0x3b, 0x20, 0x6e, 0xef, 0x50, 0x9f, 0x6b, + 0x3b, 0x6d, 0x87, 0x75, 0xac, 0xd0, 0x2f, 0xce, 0xa3, 0xcf, 0x53, 0x9e, 0x95, 0xee, 0xa0, 0xd9, + 0x64, 0xff, 0xf4, 0x0e, 0x57, 0x8e, 0x07, 0xa2, 0xeb, 0x0a, 0xeb, 0x32, 0xfb, 0xfe, 0x11, 0xfb, + 0xa7, 0x77, 0xc8, 0xfe, 0x88, 0xce, 0xab, 0x6d, 0xc7, 0x69, 0x77, 0xc8, 0x8a, 0xd9, 0xb3, 0x56, + 0x4c, 0xdb, 0x76, 0x7c, 0xd3, 0xb7, 0x1c, 0xdb, 0xe3, 0xbd, 0xf8, 0x73, 0x0d, 0x2a, 0x06, 0xf1, + 0x7a, 0x8e, 0xed, 0x91, 0x4d, 0x62, 0xb6, 0x88, 0x8b, 0xae, 0x01, 0x34, 0x3b, 0x7d, 0xcf, 0x27, + 0x6e, 0xc3, 0x6a, 0xd5, 0xb4, 0x45, 0x6d, 0x69, 0xd2, 0x28, 0x08, 0xca, 0x56, 0x0b, 0x5d, 0x81, + 0x42, 0x97, 0x74, 0x0f, 0x79, 0x6f, 0x86, 0xf5, 0x4e, 0x73, 0xc2, 0x56, 0x0b, 0xe9, 0x30, 0xed, + 0x92, 0x81, 0xe5, 0x59, 0x8e, 0x5d, 0xcb, 0x2e, 0x6a, 0x4b, 0x59, 0x23, 0x68, 0xd3, 0x81, 0xae, + 0xf9, 0xc2, 0x6f, 0xf8, 0xc4, 0xed, 0xd6, 0x26, 0xf9, 0x40, 0x4a, 0x38, 0x20, 0x6e, 0x17, 0x7f, + 0x36, 0x05, 0x25, 0xc3, 0xb4, 0xdb, 0xc4, 0x20, 0x1f, 0xf5, 0x89, 0xe7, 0xa3, 0x2a, 0x64, 0x8f, + 0xc9, 0x29, 0x83, 0x2f, 0x19, 0xf4, 0x93, 0x8f, 0xb7, 0xdb, 0xa4, 0x41, 0x6c, 0x0e, 0x5c, 0xa2, + 0xe3, 0xed, 0x36, 0xa9, 0xdb, 0x2d, 0x34, 0x07, 0x53, 0x1d, 0xab, 0x6b, 0xf9, 0x02, 0x95, 0x37, + 0x22, 0xea, 0x4c, 0xc6, 0xd4, 0x59, 0x07, 0xf0, 0x1c, 0xd7, 0x6f, 0x38, 0x6e, 0x8b, 0xb8, 0xb5, + 0xa9, 0x45, 0x6d, 0xa9, 0xb2, 0x7a, 0x6b, 0x59, 0x5d, 0x88, 0x65, 0x55, 0xa1, 0xe5, 0x7d, 0xc7, + 0xf5, 0xf7, 0x28, 0xaf, 0x51, 0xf0, 0xe4, 0x27, 0x7a, 0x07, 0x8a, 0x4c, 0x88, 0x6f, 0xba, 0x6d, + 0xe2, 0xd7, 0x72, 0x4c, 0xca, 0xed, 0x33, 0xa4, 0x1c, 0x30, 0x66, 0x83, 0xc1, 0xf3, 0x6f, 0x84, + 0xa1, 0xe4, 0x11, 0xd7, 0x32, 0x3b, 0xd6, 0xc7, 0xe6, 0x61, 0x87, 0xd4, 0xf2, 0x8b, 0xda, 0xd2, + 0xb4, 0x11, 0xa1, 0xd1, 0xf9, 0x1f, 0x93, 0x53, 0xaf, 0xe1, 0xd8, 0x9d, 0xd3, 0xda, 0x34, 0x63, + 0x98, 0xa6, 0x84, 0x3d, 0xbb, 0x73, 0xca, 0x16, 0xcd, 0xe9, 0xdb, 0x3e, 0xef, 0x2d, 0xb0, 0xde, + 0x02, 0xa3, 0xb0, 0xee, 0x25, 0xa8, 0x76, 0x2d, 0xbb, 0xd1, 0x75, 0x5a, 0x8d, 0xc0, 0x20, 0xc0, + 0x0c, 0x52, 0xe9, 0x5a, 0xf6, 0x13, 0xa7, 0x65, 0x48, 0xb3, 0x50, 0x4e, 0xf3, 0x24, 0xca, 0x59, + 0x14, 0x9c, 0xe6, 0x89, 0xca, 0xb9, 0x0c, 0xb3, 0x54, 0x66, 0xd3, 0x25, 0xa6, 0x4f, 0x42, 0xe6, + 0x12, 0x63, 0xbe, 0xd0, 0xb5, 0xec, 0x75, 0xd6, 0x13, 0xe1, 0x37, 0x4f, 0x86, 0xf8, 0xcb, 0x82, + 0xdf, 0x3c, 0x89, 0xf2, 0xe3, 0x65, 0x28, 0x04, 0x36, 0x47, 0xd3, 0x30, 0xb9, 0xbb, 0xb7, 0x5b, + 0xaf, 0x4e, 0x20, 0x80, 0xdc, 0xda, 0xfe, 0x7a, 0x7d, 0x77, 0xa3, 0xaa, 0xa1, 0x22, 0xe4, 0x37, + 0xea, 0xbc, 0x91, 0xc1, 0x8f, 0x00, 0x42, 0xeb, 0xa2, 0x3c, 0x64, 0xb7, 0xeb, 0xff, 0x55, 0x9d, + 0xa0, 0x3c, 0xcf, 0xeb, 0xc6, 0xfe, 0xd6, 0xde, 0x6e, 0x55, 0xa3, 0x83, 0xd7, 0x8d, 0xfa, 0xda, + 0x41, 0xbd, 0x9a, 0xa1, 0x1c, 0x4f, 0xf6, 0x36, 0xaa, 0x59, 0x54, 0x80, 0xa9, 0xe7, 0x6b, 0x3b, + 0xcf, 0xea, 0xd5, 0x49, 0xfc, 0x85, 0x06, 0x65, 0xb1, 0x5e, 0xdc, 0x27, 0xd0, 0x9b, 0x90, 0x3b, + 0x62, 0x7e, 0xc1, 0xb6, 0x62, 0x71, 0xf5, 0x6a, 0x6c, 0x71, 0x23, 0xbe, 0x63, 0x08, 0x5e, 0x84, + 0x21, 0x7b, 0x3c, 0xf0, 0x6a, 0x99, 0xc5, 0xec, 0x52, 0x71, 0xb5, 0xba, 0xcc, 0x1d, 0x76, 0x79, + 0x9b, 0x9c, 0x3e, 0x37, 0x3b, 0x7d, 0x62, 0xd0, 0x4e, 0x84, 0x60, 0xb2, 0xeb, 0xb8, 0x84, 0xed, + 0xd8, 0x69, 0x83, 0x7d, 0xd3, 0x6d, 0xcc, 0x16, 0x4d, 0xec, 0x56, 0xde, 0xc0, 0x5f, 0x6a, 0x00, + 0x4f, 0xfb, 0x7e, 0xba, 0x6b, 0xcc, 0xc1, 0xd4, 0x80, 0x0a, 0x16, 0x6e, 0xc1, 0x1b, 0xcc, 0x27, + 0x88, 0xe9, 0x91, 0xc0, 0x27, 0x68, 0x03, 0x5d, 0x86, 0x7c, 0xcf, 0x25, 0x83, 0xc6, 0xf1, 0x80, + 0x81, 0x4c, 0x1b, 0x39, 0xda, 0xdc, 0x1e, 0xa0, 0x1b, 0x50, 0xb2, 0xda, 0xb6, 0xe3, 0x92, 0x06, + 0x97, 0x35, 0xc5, 0x7a, 0x8b, 0x9c, 0xc6, 0xf4, 0x56, 0x58, 0xb8, 0xe0, 0x9c, 0xca, 0xb2, 0x43, + 0x49, 0xd8, 0x86, 0x22, 0x53, 0x75, 0x2c, 0xf3, 0xdd, 0x0b, 0x75, 0xcc, 0xb0, 0x61, 0xc3, 0x26, + 0x14, 0x5a, 0xe3, 0x0f, 0x01, 0x6d, 0x90, 0x0e, 0xf1, 0xc9, 0x38, 0xd1, 0x43, 0xb1, 0x49, 0x56, + 0xb5, 0x09, 0xfe, 0x91, 0x06, 0xb3, 0x11, 0xf1, 0x63, 0x4d, 0xab, 0x06, 0xf9, 0x16, 0x13, 0xc6, + 0x35, 0xc8, 0x1a, 0xb2, 0x89, 0x1e, 0xc0, 0xb4, 0x50, 0xc0, 0xab, 0x65, 0x53, 0x36, 0x4d, 0x9e, + 0xeb, 0xe4, 0xe1, 0x2f, 0x33, 0x50, 0x10, 0x13, 0xdd, 0xeb, 0xa1, 0x35, 0x28, 0xbb, 0xbc, 0xd1, + 0x60, 0xf3, 0x11, 0x1a, 0xe9, 0xe9, 0x41, 0x68, 0x73, 0xc2, 0x28, 0x89, 0x21, 0x8c, 0x8c, 0xfe, + 0x03, 0x8a, 0x52, 0x44, 0xaf, 0xef, 0x0b, 0x93, 0xd7, 0xa2, 0x02, 0xc2, 0xfd, 0xb7, 0x39, 0x61, + 0x80, 0x60, 0x7f, 0xda, 0xf7, 0xd1, 0x01, 0xcc, 0xc9, 0xc1, 0x7c, 0x36, 0x42, 0x8d, 0x2c, 0x93, + 0xb2, 0x18, 0x95, 0x32, 0xbc, 0x54, 0x9b, 0x13, 0x06, 0x12, 0xe3, 0x95, 0x4e, 0x55, 0x25, 0xff, + 0x84, 0x07, 0xef, 0x21, 0x95, 0x0e, 0x4e, 0xec, 0x61, 0x95, 0x0e, 0x4e, 0xec, 0x47, 0x05, 0xc8, + 0x8b, 0x16, 0xfe, 0x4d, 0x06, 0x40, 0xae, 0xc6, 0x5e, 0x0f, 0x6d, 0x40, 0xc5, 0x15, 0xad, 0x88, + 0xb5, 0xae, 0x24, 0x5a, 0x4b, 0x2c, 0xe2, 0x84, 0x51, 0x96, 0x83, 0xb8, 0x72, 0x6f, 0x43, 0x29, + 0x90, 0x12, 0x1a, 0x6c, 0x3e, 0xc1, 0x60, 0x81, 0x84, 0xa2, 0x1c, 0x40, 0x4d, 0xf6, 0x3e, 0x5c, + 0x0c, 0xc6, 0x27, 0xd8, 0xec, 0xc6, 0x08, 0x9b, 0x05, 0x02, 0x67, 0xa5, 0x04, 0xd5, 0x6a, 0xaa, + 0x62, 0xa1, 0xd9, 0xe6, 0x13, 0xcc, 0x36, 0xac, 0x18, 0x35, 0x1c, 0xd0, 0x7c, 0xc9, 0x9b, 0xf8, + 0x77, 0x59, 0xc8, 0xaf, 0x3b, 0xdd, 0x9e, 0xe9, 0xd2, 0xd5, 0xc8, 0xb9, 0xc4, 0xeb, 0x77, 0x7c, + 0x66, 0xae, 0xca, 0xea, 0xcd, 0xa8, 0x44, 0xc1, 0x26, 0xff, 0x1a, 0x8c, 0xd5, 0x10, 0x43, 0xe8, + 0x60, 0x91, 0x1e, 0x33, 0xe7, 0x18, 0x2c, 0x92, 0xa3, 0x18, 0x22, 0x1d, 0x39, 0x1b, 0x3a, 0xb2, + 0x0e, 0xf9, 0x01, 0x71, 0xc3, 0x94, 0xbe, 0x39, 0x61, 0x48, 0x02, 0xba, 0x07, 0x33, 0xf1, 0xf4, + 0x32, 0x25, 0x78, 0x2a, 0xcd, 0x68, 0x36, 0xba, 0x09, 0xa5, 0x48, 0x8e, 0xcb, 0x09, 0xbe, 0x62, + 0x57, 0x49, 0x71, 0x97, 0x64, 0x5c, 0xa5, 0xf9, 0xb8, 0xb4, 0x39, 0x21, 0x23, 0x6b, 0x24, 0x98, + 0x4c, 0x47, 0x83, 0x09, 0xfe, 0x4f, 0x28, 0x47, 0x0c, 0x41, 0xf3, 0x4b, 0xfd, 0xbd, 0x67, 0x6b, + 0x3b, 0x3c, 0x19, 0x3d, 0x66, 0xf9, 0xc7, 0xa8, 0x6a, 0x34, 0xa7, 0xed, 0xd4, 0xf7, 0xf7, 0xab, + 0x19, 0x54, 0x86, 0xc2, 0xee, 0xde, 0x41, 0x83, 0x73, 0x65, 0xf1, 0x5b, 0x81, 0x04, 0x91, 0xcc, + 0x94, 0x1c, 0x36, 0xa1, 0xe4, 0x30, 0x4d, 0xe6, 0xb0, 0x4c, 0x98, 0xc3, 0xb2, 0x8f, 0x2a, 0x50, + 0xe2, 0xc6, 0x6b, 0xf4, 0x6d, 0x9a, 0x47, 0x7f, 0xa1, 0x01, 0x84, 0xae, 0x82, 0x56, 0x20, 0xdf, + 0xe4, 0xc2, 0x6b, 0x1a, 0x8b, 0x34, 0x17, 0x13, 0xd7, 0xc3, 0x90, 0x5c, 0xe8, 0x75, 0xc8, 0x7b, + 0xfd, 0x66, 0x93, 0x78, 0x32, 0x9f, 0x5d, 0x8e, 0x07, 0x3b, 0x11, 0x8a, 0x0c, 0xc9, 0x47, 0x87, + 0xbc, 0x30, 0xad, 0x4e, 0x9f, 0x65, 0xb7, 0xd1, 0x43, 0x04, 0x1f, 0xfe, 0xa9, 0x06, 0x45, 0x65, + 0x67, 0x7e, 0xc3, 0x08, 0x7b, 0x15, 0x0a, 0x4c, 0x07, 0xd2, 0x12, 0x31, 0x76, 0xda, 0x08, 0x09, + 0xe8, 0xdf, 0xa1, 0x20, 0xb7, 0xb7, 0x0c, 0xb3, 0xb5, 0x64, 0xb1, 0x7b, 0x3d, 0x23, 0x64, 0xc5, + 0xdb, 0x70, 0x81, 0x59, 0xa5, 0x49, 0x4f, 0xce, 0xd2, 0x8e, 0xea, 0xd9, 0x52, 0x8b, 0x9d, 0x2d, + 0x75, 0x98, 0xee, 0x1d, 0x9d, 0x7a, 0x56, 0xd3, 0xec, 0x08, 0x2d, 0x82, 0x36, 0x7e, 0x17, 0x90, + 0x2a, 0x6c, 0x9c, 0xe9, 0xe2, 0x32, 0x14, 0x37, 0x4d, 0xef, 0x48, 0xa8, 0x84, 0x3f, 0x80, 0x12, + 0x6f, 0x8e, 0x65, 0x43, 0x04, 0x93, 0x47, 0xa6, 0x77, 0xc4, 0x14, 0x2f, 0x1b, 0xec, 0x1b, 0x5f, + 0x80, 0x99, 0x7d, 0xdb, 0xec, 0x79, 0x47, 0x8e, 0xcc, 0x02, 0xf4, 0xe6, 0x50, 0x0d, 0x69, 0x63, + 0x21, 0xde, 0x85, 0x19, 0x97, 0x74, 0x4d, 0xcb, 0xb6, 0xec, 0x76, 0xe3, 0xf0, 0xd4, 0x27, 0x9e, + 0xb8, 0x58, 0x54, 0x02, 0xf2, 0x23, 0x4a, 0xa5, 0xaa, 0x1d, 0x76, 0x9c, 0x43, 0x11, 0x0e, 0xd8, + 0x37, 0xfe, 0xb5, 0x06, 0xa5, 0xf7, 0x4d, 0xbf, 0x29, 0xad, 0x80, 0xb6, 0xa0, 0x12, 0x04, 0x01, + 0x46, 0x11, 0xba, 0xc4, 0x52, 0x11, 0x1b, 0x23, 0x8f, 0x9c, 0x32, 0x8b, 0x94, 0x9b, 0x2a, 0x81, + 0x89, 0x32, 0xed, 0x26, 0xe9, 0x04, 0xa2, 0x32, 0xe9, 0xa2, 0x18, 0xa3, 0x2a, 0x4a, 0x25, 0x3c, + 0x9a, 0x09, 0xd3, 0x34, 0x77, 0xcb, 0x9f, 0x65, 0x00, 0x0d, 0xeb, 0xf0, 0x75, 0x4f, 0x2e, 0xb7, + 0xa1, 0xe2, 0xf9, 0xa6, 0xeb, 0x37, 0x62, 0xd7, 0xae, 0x32, 0xa3, 0x06, 0x81, 0xec, 0x2e, 0xcc, + 0xf4, 0x5c, 0xa7, 0xed, 0x12, 0xcf, 0x6b, 0xd8, 0x8e, 0x6f, 0xbd, 0x38, 0x15, 0x87, 0xbf, 0x8a, + 0x24, 0xef, 0x32, 0x2a, 0xaa, 0x43, 0xfe, 0x85, 0xd5, 0xf1, 0x89, 0xeb, 0xd5, 0xa6, 0x16, 0xb3, + 0x4b, 0x95, 0xd5, 0x07, 0x67, 0x59, 0x6d, 0xf9, 0x1d, 0xc6, 0x7f, 0x70, 0xda, 0x23, 0x86, 0x1c, + 0xab, 0x1e, 0xa8, 0x72, 0x91, 0x03, 0xd5, 0x6d, 0x80, 0x90, 0x9f, 0x46, 0xad, 0xdd, 0xbd, 0xa7, + 0xcf, 0x0e, 0xaa, 0x13, 0xa8, 0x04, 0xd3, 0xbb, 0x7b, 0x1b, 0xf5, 0x9d, 0x3a, 0x8d, 0x6b, 0x78, + 0x45, 0xda, 0x46, 0xb5, 0x21, 0x9a, 0x87, 0xe9, 0x97, 0x94, 0x2a, 0xef, 0xa5, 0x59, 0x23, 0xcf, + 0xda, 0x5b, 0x2d, 0xfc, 0xc3, 0x0c, 0x94, 0xc5, 0x2e, 0x18, 0x6b, 0x2b, 0xaa, 0x10, 0x99, 0x08, + 0x04, 0x3d, 0xbd, 0xf1, 0xdd, 0xd1, 0x12, 0x87, 0x44, 0xd9, 0xa4, 0xee, 0xce, 0x17, 0x9b, 0xb4, + 0x84, 0x59, 0x83, 0x36, 0xba, 0x07, 0xd5, 0x26, 0x77, 0xf7, 0x58, 0x4e, 0x32, 0x66, 0x04, 0x5d, + 0x49, 0x49, 0xe5, 0x60, 0xb7, 0x99, 0x9e, 0xc8, 0x49, 0x05, 0xa3, 0x24, 0x37, 0x12, 0xa5, 0xa1, + 0xdb, 0x90, 0x23, 0x03, 0x62, 0xfb, 0x5e, 0xad, 0xc8, 0x02, 0x58, 0x59, 0x9e, 0x13, 0xeb, 0x94, + 0x6a, 0x88, 0x4e, 0xfc, 0x6f, 0x70, 0x81, 0x9d, 0xc7, 0x1f, 0xbb, 0xa6, 0xad, 0x5e, 0x1c, 0x0e, + 0x0e, 0x76, 0x84, 0xe9, 0xe8, 0x27, 0xaa, 0x40, 0x66, 0x6b, 0x43, 0x4c, 0x34, 0xb3, 0xb5, 0x81, + 0x3f, 0xd5, 0x00, 0xa9, 0xe3, 0xc6, 0xb2, 0x65, 0x4c, 0xb8, 0x84, 0xcf, 0x86, 0xf0, 0x73, 0x30, + 0x45, 0x5c, 0xd7, 0x71, 0x99, 0xd5, 0x0a, 0x06, 0x6f, 0xe0, 0x5b, 0x42, 0x07, 0x83, 0x0c, 0x9c, + 0xe3, 0xc0, 0x31, 0xb8, 0x34, 0x2d, 0x50, 0x75, 0x1b, 0x66, 0x23, 0x5c, 0x63, 0x05, 0xd2, 0xbb, + 0x70, 0x91, 0x09, 0xdb, 0x26, 0xa4, 0xb7, 0xd6, 0xb1, 0x06, 0xa9, 0xa8, 0x3d, 0xb8, 0x14, 0x67, + 0xfc, 0x76, 0x6d, 0x84, 0xdf, 0x12, 0x88, 0x07, 0x56, 0x97, 0x1c, 0x38, 0x3b, 0xe9, 0xba, 0xd1, + 0xe8, 0x78, 0x4c, 0x4e, 0x3d, 0x91, 0x71, 0xd8, 0x37, 0xfe, 0xa5, 0x06, 0x97, 0x87, 0x86, 0x7f, + 0xcb, 0xab, 0xba, 0x00, 0xd0, 0xa6, 0xdb, 0x87, 0xb4, 0x68, 0x07, 0xbf, 0xc9, 0x2a, 0x94, 0x40, + 0x4f, 0x1a, 0x60, 0x4a, 0x42, 0xcf, 0x23, 0xc8, 0x3d, 0x61, 0x45, 0x24, 0x65, 0x56, 0x93, 0x72, + 0x56, 0xb6, 0xd9, 0xe5, 0x57, 0xdb, 0x82, 0xc1, 0xbe, 0x59, 0x7e, 0x25, 0xc4, 0x7d, 0x66, 0xec, + 0xf0, 0x3c, 0x5e, 0x30, 0x82, 0x36, 0x45, 0x6f, 0x76, 0x2c, 0x62, 0xfb, 0xac, 0x77, 0x92, 0xf5, + 0x2a, 0x14, 0xbc, 0x0c, 0x55, 0x8e, 0xb4, 0xd6, 0x6a, 0x29, 0xb9, 0x3c, 0x90, 0xa7, 0x45, 0xe5, + 0xe1, 0x5f, 0x69, 0x70, 0x41, 0x19, 0x30, 0x96, 0xed, 0x5e, 0x81, 0x1c, 0x2f, 0x95, 0x89, 0x3c, + 0x32, 0x17, 0x1d, 0xc5, 0x61, 0x0c, 0xc1, 0x83, 0x96, 0x21, 0xcf, 0xbf, 0xe4, 0x61, 0x25, 0x99, + 0x5d, 0x32, 0xe1, 0xdb, 0x30, 0x2b, 0x48, 0xa4, 0xeb, 0x24, 0x6d, 0x13, 0x66, 0x50, 0xfc, 0x09, + 0xcc, 0x45, 0xd9, 0xc6, 0x9a, 0x92, 0xa2, 0x64, 0xe6, 0x3c, 0x4a, 0xae, 0x49, 0x25, 0x9f, 0xf5, + 0x5a, 0x4a, 0xda, 0x8b, 0xaf, 0xba, 0xba, 0x22, 0x99, 0xd8, 0x8a, 0x04, 0x13, 0x90, 0x22, 0xbe, + 0xd3, 0x09, 0xcc, 0xca, 0xed, 0xb0, 0x63, 0x79, 0xc1, 0x61, 0xe8, 0x63, 0x40, 0x2a, 0xf1, 0xbb, + 0x56, 0x68, 0x83, 0xbc, 0x70, 0xcd, 0x76, 0x97, 0x04, 0xa1, 0x9e, 0x9e, 0x32, 0x55, 0xe2, 0x58, + 0xc1, 0xf1, 0x8f, 0x1a, 0x94, 0xd6, 0x3a, 0xa6, 0xdb, 0x95, 0x8b, 0xf5, 0x36, 0xe4, 0xf8, 0xf1, + 0x55, 0x5c, 0x07, 0xef, 0x44, 0xc5, 0xa8, 0xbc, 0xbc, 0xb1, 0xc6, 0x0f, 0xbb, 0x62, 0x14, 0x5d, + 0x5c, 0x51, 0x31, 0xde, 0x88, 0x55, 0x90, 0x37, 0xd0, 0xab, 0x30, 0x65, 0xd2, 0x21, 0x2c, 0xa0, + 0x54, 0xe2, 0x17, 0x07, 0x26, 0x8d, 0x1d, 0x35, 0x38, 0x17, 0x7e, 0x13, 0x8a, 0x0a, 0x02, 0xbd, + 0x0f, 0x3d, 0xae, 0x8b, 0xe3, 0xc4, 0xda, 0xfa, 0xc1, 0xd6, 0x73, 0x7e, 0x4d, 0xaa, 0x00, 0x6c, + 0xd4, 0x83, 0x76, 0x06, 0x7f, 0x20, 0x46, 0x89, 0x90, 0xa3, 0xea, 0xa3, 0xa5, 0xe9, 0x93, 0x39, + 0x97, 0x3e, 0x27, 0x50, 0x16, 0xd3, 0x1f, 0x6b, 0x0f, 0xbc, 0x0e, 0x39, 0x26, 0x4f, 0x6e, 0x81, + 0xf9, 0x04, 0x58, 0x19, 0x2d, 0x38, 0x23, 0x9e, 0x81, 0xf2, 0xbe, 0x6f, 0xfa, 0x7d, 0x4f, 0x6e, + 0x81, 0x3f, 0x68, 0x50, 0x91, 0x94, 0x71, 0xcb, 0x56, 0xf2, 0xc6, 0xcd, 0x83, 0x70, 0x70, 0xdf, + 0xbe, 0x04, 0xb9, 0xd6, 0xe1, 0xbe, 0xf5, 0xb1, 0x2c, 0x31, 0x8a, 0x16, 0xa5, 0x77, 0x38, 0x0e, + 0xaf, 0xf3, 0x8b, 0x16, 0xbd, 0x9e, 0xb9, 0xe6, 0x0b, 0x7f, 0xcb, 0x6e, 0x91, 0x13, 0x76, 0x0a, + 0x9a, 0x34, 0x42, 0x02, 0xbb, 0x51, 0x89, 0xf7, 0x00, 0x76, 0xf4, 0x51, 0xdf, 0x07, 0x66, 0xe1, + 0xc2, 0x5a, 0xdf, 0x3f, 0xaa, 0xdb, 0xe6, 0x61, 0x47, 0x06, 0x0d, 0x3c, 0x07, 0x88, 0x12, 0x37, + 0x2c, 0x4f, 0xa5, 0xd6, 0x61, 0x96, 0x52, 0x89, 0xed, 0x5b, 0x4d, 0x25, 0xc2, 0xc8, 0x3c, 0xa2, + 0xc5, 0xf2, 0x88, 0xe9, 0x79, 0x2f, 0x1d, 0xb7, 0x25, 0xa6, 0x16, 0xb4, 0xf1, 0x06, 0x17, 0xfe, + 0xcc, 0x8b, 0x64, 0x8a, 0xaf, 0x2b, 0x65, 0x29, 0x94, 0xf2, 0x98, 0xf8, 0x23, 0xa4, 0xe0, 0x07, + 0x70, 0x51, 0x72, 0x8a, 0x92, 0xce, 0x08, 0xe6, 0x3d, 0xb8, 0x26, 0x99, 0xd7, 0x8f, 0xe8, 0x5d, + 0xe0, 0xa9, 0x00, 0xfc, 0xa6, 0x7a, 0x3e, 0x82, 0x5a, 0xa0, 0x27, 0x3b, 0xfa, 0x39, 0x1d, 0x55, + 0x81, 0xbe, 0x27, 0xf6, 0x4c, 0xc1, 0x60, 0xdf, 0x94, 0xe6, 0x3a, 0x9d, 0x20, 0x2b, 0xd3, 0x6f, + 0xbc, 0x0e, 0xf3, 0x52, 0x86, 0x38, 0x94, 0x45, 0x85, 0x0c, 0x29, 0x94, 0x24, 0x44, 0x18, 0x8c, + 0x0e, 0x1d, 0x6d, 0x76, 0x95, 0x33, 0x6a, 0x5a, 0x26, 0x53, 0x53, 0x64, 0x5e, 0xe4, 0x3b, 0x82, + 0x2a, 0xa6, 0x06, 0x6d, 0x41, 0xa6, 0x02, 0x54, 0xb2, 0x58, 0x08, 0x4a, 0x1e, 0x5a, 0x88, 0x21, + 0xd1, 0x1f, 0xc2, 0x42, 0xa0, 0x04, 0xb5, 0xdb, 0x53, 0xe2, 0x76, 0x2d, 0xcf, 0x53, 0xea, 0x04, + 0x49, 0x13, 0xbf, 0x03, 0x93, 0x3d, 0x22, 0x62, 0x4a, 0x71, 0x15, 0x2d, 0xf3, 0x57, 0xbb, 0x65, + 0x65, 0x30, 0xeb, 0xc7, 0x2d, 0xb8, 0x2e, 0xa5, 0x73, 0x8b, 0x26, 0x8a, 0x8f, 0x2b, 0x25, 0xef, + 0x90, 0xdc, 0xac, 0xc3, 0x77, 0xc8, 0x2c, 0x5f, 0xfb, 0xa0, 0x60, 0xf5, 0x2e, 0x37, 0xa4, 0xf4, + 0xad, 0xb1, 0x72, 0xc5, 0x36, 0xb7, 0x69, 0xe0, 0x92, 0x63, 0x09, 0x3b, 0x84, 0xb9, 0xa8, 0x27, + 0x8f, 0x15, 0xc6, 0xe6, 0x60, 0xca, 0x77, 0x8e, 0x89, 0x0c, 0x62, 0xbc, 0x21, 0x15, 0x0e, 0xdc, + 0x7c, 0x2c, 0x85, 0xcd, 0x50, 0x18, 0xdb, 0x92, 0xe3, 0xea, 0x4b, 0x57, 0x53, 0x9e, 0x7f, 0x78, + 0x03, 0xef, 0xc2, 0xa5, 0x78, 0x98, 0x18, 0x4b, 0xe5, 0xe7, 0x7c, 0x03, 0x27, 0x45, 0x92, 0xb1, + 0xe4, 0xbe, 0x17, 0x06, 0x03, 0x25, 0xa0, 0x8c, 0x25, 0xd2, 0x00, 0x3d, 0x29, 0xbe, 0xfc, 0x2b, + 0xf6, 0x6b, 0x10, 0x6e, 0xc6, 0x12, 0xe6, 0x85, 0xc2, 0xc6, 0x5f, 0xfe, 0x30, 0x46, 0x64, 0x47, + 0xc6, 0x08, 0xe1, 0x24, 0x61, 0x14, 0xfb, 0x16, 0x36, 0x9d, 0xc0, 0x08, 0x03, 0xe8, 0xb8, 0x18, + 0x34, 0x87, 0x04, 0x18, 0xac, 0x21, 0x37, 0xb6, 0x1a, 0x76, 0xc7, 0x5a, 0x8c, 0xf7, 0xc3, 0xd8, + 0x39, 0x14, 0x99, 0xc7, 0x12, 0xfc, 0x01, 0x2c, 0xa6, 0x07, 0xe5, 0x71, 0x24, 0xdf, 0xc7, 0x50, + 0x08, 0x0e, 0x94, 0xca, 0x8b, 0x77, 0x11, 0xf2, 0xbb, 0x7b, 0xfb, 0x4f, 0xd7, 0xd6, 0xeb, 0x55, + 0x6d, 0xf5, 0xef, 0x59, 0xc8, 0x6c, 0x3f, 0x47, 0xff, 0x0d, 0x53, 0xfc, 0xc9, 0x67, 0xc4, 0x3b, + 0x9f, 0x3e, 0xea, 0x55, 0x0b, 0x5f, 0xfd, 0xf4, 0xcf, 0x7f, 0xfb, 0x22, 0x73, 0x09, 0x5f, 0x58, + 0x19, 0xbc, 0x61, 0x76, 0x7a, 0x47, 0xe6, 0xca, 0xf1, 0x60, 0x85, 0xe5, 0x84, 0x87, 0xda, 0x7d, + 0xf4, 0x1c, 0xb2, 0x4f, 0xfb, 0x3e, 0x4a, 0x7d, 0x04, 0xd4, 0xd3, 0x5f, 0xbb, 0xb0, 0xce, 0x24, + 0xcf, 0xe1, 0x19, 0x55, 0x72, 0xaf, 0xef, 0x53, 0xb9, 0x03, 0x28, 0xaa, 0x0f, 0x56, 0x67, 0x3e, + 0x0f, 0xea, 0x67, 0x3f, 0x86, 0x61, 0xcc, 0xf0, 0xae, 0xe2, 0xcb, 0x2a, 0x1e, 0x7f, 0x57, 0x53, + 0xe7, 0x73, 0x70, 0x62, 0xa3, 0xd4, 0x17, 0x44, 0x3d, 0xfd, 0x91, 0x2c, 0x79, 0x3e, 0xfe, 0x89, + 0x4d, 0xe5, 0x3a, 0xe2, 0x91, 0xac, 0xe9, 0xa3, 0xeb, 0x09, 0xef, 0x28, 0xea, 0x8b, 0x81, 0xbe, + 0x98, 0xce, 0x20, 0x90, 0x6e, 0x30, 0xa4, 0x2b, 0xf8, 0x92, 0x8a, 0xd4, 0x0c, 0xf8, 0x1e, 0x6a, + 0xf7, 0x57, 0x8f, 0x60, 0x8a, 0xd5, 0x39, 0x51, 0x43, 0x7e, 0xe8, 0x09, 0x15, 0xda, 0x94, 0x1d, + 0x10, 0xa9, 0x90, 0xe2, 0x79, 0x86, 0x36, 0x8b, 0x2b, 0x01, 0x1a, 0x2b, 0x75, 0x3e, 0xd4, 0xee, + 0x2f, 0x69, 0xaf, 0x69, 0xab, 0xff, 0x3f, 0x09, 0x53, 0xac, 0x74, 0x84, 0x7a, 0x00, 0x61, 0x51, + 0x30, 0x3e, 0xcf, 0xa1, 0x32, 0x63, 0x7c, 0x9e, 0xc3, 0xf5, 0x44, 0x7c, 0x9d, 0x21, 0xcf, 0xe3, + 0xb9, 0x00, 0x99, 0xfd, 0x9e, 0x60, 0x85, 0x15, 0x89, 0xa8, 0x59, 0x5f, 0x42, 0x51, 0x29, 0xee, + 0xa1, 0x24, 0x89, 0x91, 0xea, 0x60, 0x7c, 0x9b, 0x24, 0x54, 0x06, 0xf1, 0x4d, 0x06, 0x7a, 0x0d, + 0xd7, 0x54, 0xe3, 0x72, 0x5c, 0x97, 0x71, 0x52, 0xe0, 0xcf, 0x34, 0xa8, 0x44, 0x0b, 0x7c, 0xe8, + 0x66, 0x82, 0xe8, 0x78, 0x9d, 0x50, 0xbf, 0x35, 0x9a, 0x29, 0x55, 0x05, 0x8e, 0x7f, 0x4c, 0x48, + 0xcf, 0xa4, 0x9c, 0xc2, 0xf6, 0xe8, 0x7b, 0x1a, 0xcc, 0xc4, 0xca, 0x76, 0x28, 0x09, 0x62, 0xa8, + 0x28, 0xa8, 0xdf, 0x3e, 0x83, 0x4b, 0x68, 0x72, 0x97, 0x69, 0x72, 0x03, 0x5f, 0x1d, 0x36, 0x86, + 0x6f, 0x75, 0x89, 0xef, 0x08, 0x6d, 0x56, 0xff, 0x91, 0x85, 0xfc, 0x3a, 0xff, 0xf1, 0x17, 0xf2, + 0xa1, 0x10, 0x54, 0xc2, 0xd0, 0x42, 0x52, 0x55, 0x22, 0x3c, 0xb2, 0xeb, 0xd7, 0x53, 0xfb, 0x85, + 0x0a, 0x77, 0x98, 0x0a, 0x8b, 0xf8, 0x4a, 0xa0, 0x82, 0xf8, 0x91, 0xd9, 0x0a, 0xbf, 0x7c, 0xaf, + 0x98, 0xad, 0x16, 0x5d, 0x92, 0xff, 0xd3, 0xa0, 0xa4, 0x16, 0xac, 0xd0, 0x8d, 0xc4, 0x7a, 0x88, + 0x5a, 0xf3, 0xd2, 0xf1, 0x28, 0x16, 0x81, 0x7f, 0x8f, 0xe1, 0xdf, 0xc4, 0x0b, 0x69, 0xf8, 0x2e, + 0xe3, 0x8f, 0xaa, 0xc0, 0x4b, 0x4e, 0xc9, 0x2a, 0x44, 0x2a, 0x5a, 0xc9, 0x2a, 0x44, 0x2b, 0x56, + 0x67, 0xab, 0xd0, 0x67, 0xfc, 0x54, 0x85, 0x13, 0x80, 0xb0, 0xc2, 0x84, 0x12, 0x8d, 0xab, 0x5c, + 0x62, 0xe2, 0x3e, 0x38, 0x5c, 0x9c, 0x4a, 0xd8, 0x01, 0x31, 0xec, 0x8e, 0xe5, 0x51, 0x5f, 0x5c, + 0xfd, 0xed, 0x24, 0x14, 0x9f, 0x98, 0x96, 0xed, 0x13, 0xdb, 0xb4, 0x9b, 0x04, 0xb5, 0x61, 0x8a, + 0x65, 0xa9, 0x78, 0xe0, 0x51, 0xcb, 0x3e, 0xf1, 0xc0, 0x13, 0xa9, 0x89, 0xe0, 0xdb, 0x0c, 0xfa, + 0x3a, 0xd6, 0x03, 0xe8, 0x6e, 0x28, 0x7f, 0x85, 0xd5, 0x33, 0xe8, 0x94, 0x8f, 0x21, 0xc7, 0xeb, + 0x17, 0x28, 0x26, 0x2d, 0x52, 0xe7, 0xd0, 0xaf, 0x26, 0x77, 0xa6, 0xee, 0x32, 0x15, 0xcb, 0x63, + 0xcc, 0x14, 0xec, 0x7f, 0x00, 0xc2, 0x82, 0x59, 0xdc, 0xbe, 0x43, 0xf5, 0x35, 0x7d, 0x31, 0x9d, + 0x41, 0x00, 0xdf, 0x67, 0xc0, 0xb7, 0xf0, 0xf5, 0x44, 0xe0, 0x56, 0x30, 0x80, 0x82, 0x37, 0x61, + 0x72, 0xd3, 0xf4, 0x8e, 0x50, 0x2c, 0x09, 0x29, 0x6f, 0xbb, 0xba, 0x9e, 0xd4, 0x25, 0xa0, 0x6e, + 0x31, 0xa8, 0x05, 0x3c, 0x9f, 0x08, 0x75, 0x64, 0x7a, 0x34, 0xa6, 0xa3, 0x3e, 0x4c, 0xcb, 0xf7, + 0x5a, 0x74, 0x2d, 0x66, 0xb3, 0xe8, 0xdb, 0xae, 0xbe, 0x90, 0xd6, 0x2d, 0x00, 0x97, 0x18, 0x20, + 0xc6, 0xd7, 0x92, 0x8d, 0x2a, 0xd8, 0x1f, 0x6a, 0xf7, 0x5f, 0xd3, 0x56, 0x7f, 0x50, 0x85, 0x49, + 0x7a, 0x5e, 0xa2, 0x59, 0x24, 0xbc, 0x66, 0xc6, 0x2d, 0x3c, 0x54, 0xdc, 0x89, 0x5b, 0x78, 0xf8, + 0x86, 0x9a, 0x90, 0x45, 0xd8, 0x4f, 0x60, 0x09, 0xe3, 0xa2, 0x33, 0xf6, 0xa1, 0xa8, 0x5c, 0x46, + 0x51, 0x82, 0xc4, 0x68, 0xe9, 0x28, 0x9e, 0x45, 0x12, 0x6e, 0xb2, 0x78, 0x91, 0x81, 0xea, 0xf8, + 0x62, 0x14, 0xb4, 0xc5, 0xd9, 0x28, 0xea, 0x27, 0x50, 0x52, 0x6f, 0xad, 0x28, 0x41, 0x68, 0xac, + 0x36, 0x15, 0x8f, 0x15, 0x49, 0x97, 0xde, 0x04, 0xa7, 0x09, 0x7e, 0xf0, 0x2b, 0x79, 0x29, 0xfa, + 0x47, 0x90, 0x17, 0x77, 0xd9, 0xa4, 0xf9, 0x46, 0xab, 0x59, 0x49, 0xf3, 0x8d, 0x5d, 0x84, 0x13, + 0x8e, 0x24, 0x0c, 0x96, 0x9e, 0xd9, 0x65, 0x80, 0x16, 0x90, 0x8f, 0x89, 0x9f, 0x06, 0x19, 0xd6, + 0x67, 0xd2, 0x20, 0x95, 0xfb, 0xd2, 0x48, 0xc8, 0x36, 0xf1, 0xc5, 0x5e, 0x96, 0x97, 0x11, 0x94, + 0x22, 0x51, 0x8d, 0x86, 0x78, 0x14, 0x4b, 0xea, 0x29, 0x32, 0x44, 0x15, 0xa1, 0x10, 0xfd, 0x2f, + 0x40, 0x78, 0xf1, 0x8e, 0x1f, 0x0c, 0x12, 0xab, 0x77, 0xf1, 0x83, 0x41, 0xf2, 0xdd, 0x3d, 0xc1, + 0x83, 0x43, 0x70, 0x7e, 0x92, 0xa5, 0xf0, 0x3f, 0xd6, 0x00, 0x0d, 0x5f, 0xd4, 0xd1, 0x83, 0x64, + 0x88, 0xc4, 0xc2, 0xa0, 0xfe, 0xca, 0xf9, 0x98, 0x53, 0xa3, 0x67, 0xa8, 0x57, 0x93, 0x0d, 0xe9, + 0xbd, 0xa4, 0x9a, 0x7d, 0xae, 0x41, 0x39, 0x72, 0xd5, 0x47, 0x77, 0x52, 0xd6, 0x39, 0x56, 0x5c, + 0xd4, 0xef, 0x9e, 0xc9, 0x97, 0x7a, 0x76, 0x52, 0x76, 0x85, 0x3c, 0x37, 0x7e, 0x5f, 0x83, 0x4a, + 0xb4, 0x3e, 0x80, 0x52, 0x00, 0x86, 0x2a, 0x94, 0xfa, 0xd2, 0xd9, 0x8c, 0xe7, 0x58, 0xad, 0xf0, + 0x28, 0xf9, 0x11, 0xe4, 0x45, 0x59, 0x21, 0xc9, 0x2d, 0xa2, 0x05, 0xce, 0x24, 0xb7, 0x88, 0xd5, + 0x24, 0xd2, 0xdc, 0x82, 0xde, 0xd0, 0x15, 0x4f, 0x14, 0xc5, 0x87, 0x34, 0xc8, 0xd1, 0x9e, 0x18, + 0xab, 0x5c, 0x8c, 0x84, 0x0c, 0x3d, 0x51, 0x96, 0x1e, 0x50, 0x8a, 0xc4, 0x33, 0x3c, 0x31, 0x5e, + 0xb9, 0x48, 0xf3, 0x44, 0x86, 0xaa, 0x78, 0x62, 0x58, 0x29, 0x48, 0xf2, 0xc4, 0xa1, 0xf2, 0x6d, + 0x92, 0x27, 0x0e, 0x17, 0x1b, 0xd2, 0xd6, 0x96, 0x81, 0x47, 0x3c, 0x71, 0x36, 0xa1, 0xb2, 0x80, + 0x5e, 0x49, 0xb1, 0x69, 0x62, 0x69, 0x58, 0x7f, 0xf5, 0x9c, 0xdc, 0xa3, 0x3d, 0x80, 0xaf, 0x86, + 0xf4, 0x80, 0x9f, 0x6b, 0x30, 0x97, 0x54, 0x9a, 0x40, 0x29, 0x60, 0x29, 0x75, 0x65, 0x7d, 0xf9, + 0xbc, 0xec, 0xe7, 0xb0, 0x5b, 0xe0, 0x13, 0x8f, 0xaa, 0xbf, 0xff, 0x6a, 0x41, 0xfb, 0xd3, 0x57, + 0x0b, 0xda, 0x5f, 0xbe, 0x5a, 0xd0, 0x7e, 0xf2, 0xd7, 0x85, 0x89, 0xc3, 0x1c, 0xfb, 0x7f, 0x28, + 0x6f, 0xfc, 0x33, 0x00, 0x00, 0xff, 0xff, 0xd1, 0x0e, 0xf0, 0x0b, 0x0e, 0x33, 0x00, 0x00, } diff --git a/etcdserver/etcdserverpb/rpc.proto b/etcdserver/etcdserverpb/rpc.proto index d65f36b17e7..41983f8cfb2 100644 --- a/etcdserver/etcdserverpb/rpc.proto +++ b/etcdserver/etcdserverpb/rpc.proto @@ -469,6 +469,7 @@ message RequestOp { RangeRequest request_range = 1; PutRequest request_put = 2; DeleteRangeRequest request_delete_range = 3; + TxnRequest request_txn = 4; } } @@ -478,6 +479,7 @@ message ResponseOp { RangeResponse response_range = 1; PutResponse response_put = 2; DeleteRangeResponse response_delete_range = 3; + TxnResponse response_txn = 4; } } diff --git a/etcdserver/server.go b/etcdserver/server.go index ac18b881ec2..f2f3874d56a 100644 --- a/etcdserver/server.go +++ b/etcdserver/server.go @@ -474,7 +474,7 @@ func NewServer(cfg ServerConfig) (srv *EtcdServer, err error) { srv.compactor.Run() } - srv.applyV3Base = &applierV3backend{srv} + srv.applyV3Base = srv.newApplierV3Backend() if err = srv.restoreAlarms(); err != nil { return nil, err } diff --git a/integration/v3_grpc_test.go b/integration/v3_grpc_test.go index b9c7dbc0758..83b211578c7 100644 --- a/integration/v3_grpc_test.go +++ b/integration/v3_grpc_test.go @@ -192,11 +192,22 @@ func TestV3TxnTooManyOps(t *testing.T) { }, }) } + addTxnOps := func(txn *pb.TxnRequest) { + newTxn := &pb.TxnRequest{} + addSuccessOps(newTxn) + txn.Success = append(txn.Success, + &pb.RequestOp{Request: &pb.RequestOp_RequestTxn{ + RequestTxn: newTxn, + }, + }, + ) + } tests := []func(txn *pb.TxnRequest){ addCompareOps, addSuccessOps, addFailureOps, + addTxnOps, } for i, tt := range tests { @@ -236,6 +247,27 @@ func TestV3TxnDuplicateKeys(t *testing.T) { }, }, } + txnDelReq := &pb.RequestOp{Request: &pb.RequestOp_RequestTxn{ + RequestTxn: &pb.TxnRequest{Success: []*pb.RequestOp{delInRangeReq}}, + }, + } + txnDelReqTwoSide := &pb.RequestOp{Request: &pb.RequestOp_RequestTxn{ + RequestTxn: &pb.TxnRequest{ + Success: []*pb.RequestOp{delInRangeReq}, + Failure: []*pb.RequestOp{delInRangeReq}}, + }, + } + + txnPutReq := &pb.RequestOp{Request: &pb.RequestOp_RequestTxn{ + RequestTxn: &pb.TxnRequest{Success: []*pb.RequestOp{putreq}}, + }, + } + txnPutReqTwoSide := &pb.RequestOp{Request: &pb.RequestOp_RequestTxn{ + RequestTxn: &pb.TxnRequest{ + Success: []*pb.RequestOp{putreq}, + Failure: []*pb.RequestOp{putreq}}, + }, + } kvc := toGRPC(clus.RandClient()).KV tests := []struct { @@ -258,6 +290,36 @@ func TestV3TxnDuplicateKeys(t *testing.T) { werr: rpctypes.ErrGRPCDuplicateKey, }, + // Then(Put(a), Then(Del(a))) + { + txnSuccess: []*pb.RequestOp{putreq, txnDelReq}, + + werr: rpctypes.ErrGRPCDuplicateKey, + }, + // Then(Del(a), Then(Put(a))) + { + txnSuccess: []*pb.RequestOp{delInRangeReq, txnPutReq}, + + werr: rpctypes.ErrGRPCDuplicateKey, + }, + // Then((Then(Put(a)), Else(Put(a))), (Then(Put(a)), Else(Put(a))) + { + txnSuccess: []*pb.RequestOp{txnPutReqTwoSide, txnPutReqTwoSide}, + + werr: rpctypes.ErrGRPCDuplicateKey, + }, + // Then(Del(x), (Then(Put(a)), Else(Put(a)))) + { + txnSuccess: []*pb.RequestOp{delOutOfRangeReq, txnPutReqTwoSide}, + + werr: nil, + }, + // Then(Then(Del(a)), (Then(Del(a)), Else(Del(a)))) + { + txnSuccess: []*pb.RequestOp{txnDelReq, txnDelReqTwoSide}, + + werr: nil, + }, { txnSuccess: []*pb.RequestOp{delKeyReq, delInRangeReq, delKeyReq, delInRangeReq}, @@ -469,6 +531,59 @@ func TestV3TxnRangeCompare(t *testing.T) { } } +// TestV3TxnNested tests nested txns follow paths as expected. +func TestV3TxnNestedPath(t *testing.T) { + defer testutil.AfterTest(t) + clus := NewClusterV3(t, &ClusterConfig{Size: 1}) + defer clus.Terminate(t) + + kvc := toGRPC(clus.RandClient()).KV + + cmpTrue := &pb.Compare{ + Result: pb.Compare_EQUAL, + Target: pb.Compare_VERSION, + Key: []byte("k"), + TargetUnion: &pb.Compare_Version{Version: int64(0)}, + } + cmpFalse := &pb.Compare{ + Result: pb.Compare_EQUAL, + Target: pb.Compare_VERSION, + Key: []byte("k"), + TargetUnion: &pb.Compare_Version{Version: int64(1)}, + } + + // generate random path to eval txns + topTxn := &pb.TxnRequest{} + txn := topTxn + txnPath := make([]bool, 10) + for i := range txnPath { + nextTxn := &pb.TxnRequest{} + op := &pb.RequestOp{Request: &pb.RequestOp_RequestTxn{RequestTxn: nextTxn}} + txnPath[i] = rand.Intn(2) == 0 + if txnPath[i] { + txn.Compare = append(txn.Compare, cmpTrue) + txn.Success = append(txn.Success, op) + } else { + txn.Compare = append(txn.Compare, cmpFalse) + txn.Failure = append(txn.Failure, op) + } + txn = nextTxn + } + + tresp, err := kvc.Txn(context.TODO(), topTxn) + if err != nil { + t.Fatal(err) + } + + curTxnResp := tresp + for i := range txnPath { + if curTxnResp.Succeeded != txnPath[i] { + t.Fatalf("expected path %+v, got response %+v", txnPath, *tresp) + } + curTxnResp = curTxnResp.Responses[0].Response.(*pb.ResponseOp_ResponseTxn).ResponseTxn + } +} + // TestV3PutIgnoreValue ensures that writes with ignore_value overwrites with previous key-value pair. func TestV3PutIgnoreValue(t *testing.T) { defer testutil.AfterTest(t) diff --git a/pkg/adt/interval_tree.go b/pkg/adt/interval_tree.go index 9769771ea4f..ec302e4a7a9 100644 --- a/pkg/adt/interval_tree.go +++ b/pkg/adt/interval_tree.go @@ -485,6 +485,15 @@ func (ivt *IntervalTree) Stab(iv Interval) (ivs []*IntervalValue) { return ivs } +// Union merges a given interval tree into the receiver. +func (ivt *IntervalTree) Union(inIvt IntervalTree, ivl Interval) { + f := func(n *IntervalValue) bool { + ivt.Insert(n.Ivl, n.Val) + return true + } + inIvt.Visit(ivl, f) +} + type StringComparable string func (s StringComparable) Compare(c Comparable) int { diff --git a/proxy/grpcproxy/kv.go b/proxy/grpcproxy/kv.go index c68f1b1c5fb..09b95458b38 100644 --- a/proxy/grpcproxy/kv.go +++ b/proxy/grpcproxy/kv.go @@ -99,28 +99,13 @@ func (p *kvProxy) txnToCache(reqs []*pb.RequestOp, resps []*pb.ResponseOp) { } func (p *kvProxy) Txn(ctx context.Context, r *pb.TxnRequest) (*pb.TxnResponse, error) { - txn := p.kv.Txn(ctx) - cmps := make([]clientv3.Cmp, len(r.Compare)) - thenops := make([]clientv3.Op, len(r.Success)) - elseops := make([]clientv3.Op, len(r.Failure)) - - for i := range r.Compare { - cmps[i] = (clientv3.Cmp)(*r.Compare[i]) - } - - for i := range r.Success { - thenops[i] = requestOpToOp(r.Success[i]) - } - - for i := range r.Failure { - elseops[i] = requestOpToOp(r.Failure[i]) - } - - resp, err := txn.If(cmps...).Then(thenops...).Else(elseops...).Commit() - + op := TxnRequestToOp(r) + opResp, err := p.kv.Do(ctx, op) if err != nil { return nil, err } + resp := opResp.Txn() + // txn may claim an outdated key is updated; be safe and invalidate for _, cmp := range r.Compare { p.cache.Invalidate(cmp.Key, cmp.RangeEnd) @@ -167,6 +152,10 @@ func requestOpToOp(union *pb.RequestOp) clientv3.Op { if tv.RequestDeleteRange != nil { return DelRequestToOp(tv.RequestDeleteRange) } + case *pb.RequestOp_RequestTxn: + if tv.RequestTxn != nil { + return TxnRequestToOp(tv.RequestTxn) + } } panic("unknown request") } @@ -219,3 +208,19 @@ func DelRequestToOp(r *pb.DeleteRangeRequest) clientv3.Op { } return clientv3.OpDelete(string(r.Key), opts...) } + +func TxnRequestToOp(r *pb.TxnRequest) clientv3.Op { + cmps := make([]clientv3.Cmp, len(r.Compare)) + thenops := make([]clientv3.Op, len(r.Success)) + elseops := make([]clientv3.Op, len(r.Failure)) + for i := range r.Compare { + cmps[i] = (clientv3.Cmp)(*r.Compare[i]) + } + for i := range r.Success { + thenops[i] = requestOpToOp(r.Success[i]) + } + for i := range r.Failure { + elseops[i] = requestOpToOp(r.Failure[i]) + } + return clientv3.OpTxn(cmps, thenops, elseops) +}