diff --git a/Documentation/dev-guide/api_reference_v3.md b/Documentation/dev-guide/api_reference_v3.md index 81118fe38..b0a0ffd38 100644 --- a/Documentation/dev-guide/api_reference_v3.md +++ b/Documentation/dev-guide/api_reference_v3.md @@ -59,6 +59,7 @@ for grpc-gateway | LeaseGrant | LeaseGrantRequest | LeaseGrantResponse | LeaseGrant creates a lease which expires if the server does not receive a keepAlive within a given time to live period. All keys attached to the lease will be expired and deleted if the lease expires. Each expired key generates a delete event in the event history. | | LeaseRevoke | LeaseRevokeRequest | LeaseRevokeResponse | LeaseRevoke revokes a lease. All keys attached to the lease will expire and be deleted. | | LeaseKeepAlive | LeaseKeepAliveRequest | LeaseKeepAliveResponse | LeaseKeepAlive keeps the lease alive by streaming keep alive requests from the client to the server and streaming keep alive responses from the server to the client. | +| LeaseTimeToLive | LeaseTimeToLiveRequest | LeaseTimeToLiveResponse | LeaseTimeToLive retrieves lease information. | @@ -510,6 +511,27 @@ Empty field. +##### message `LeaseTimeToLiveRequest` (etcdserver/etcdserverpb/rpc.proto) + +| Field | Description | Type | +| ----- | ----------- | ---- | +| ID | ID is the lease ID for the lease. | int64 | +| keys | keys is true to query all the keys attached to this lease. | bool | + + + +##### message `LeaseTimeToLiveResponse` (etcdserver/etcdserverpb/rpc.proto) + +| Field | Description | Type | +| ----- | ----------- | ---- | +| header | | ResponseHeader | +| ID | ID is the lease ID from the keep alive request. | int64 | +| TTL | TTL is the remaining TTL in seconds for the lease; the lease will expire in under TTL+1 seconds. | int64 | +| grantedTTL | GrantedTTL is the initial granted time in seconds upon lease creation/renewal. | int64 | +| keys | Keys is the list of keys attached to this lease. | (slice of) bytes | + + + ##### message `Member` (etcdserver/etcdserverpb/rpc.proto) | Field | Description | Type | @@ -799,6 +821,22 @@ From google paxosdb paper: Our implementation hinges around a powerful primitive +##### message `LeaseInternalRequest` (lease/leasepb/lease.proto) + +| Field | Description | Type | +| ----- | ----------- | ---- | +| LeaseTimeToLiveRequest | | etcdserverpb.LeaseTimeToLiveRequest | + + + +##### message `LeaseInternalResponse` (lease/leasepb/lease.proto) + +| Field | Description | Type | +| ----- | ----------- | ---- | +| LeaseTimeToLiveResponse | | etcdserverpb.LeaseTimeToLiveResponse | + + + ##### message `Permission` (auth/authpb/auth.proto) Permission is a single entity diff --git a/Documentation/dev-guide/apispec/swagger/rpc.swagger.json b/Documentation/dev-guide/apispec/swagger/rpc.swagger.json index 20816286c..200394968 100644 --- a/Documentation/dev-guide/apispec/swagger/rpc.swagger.json +++ b/Documentation/dev-guide/apispec/swagger/rpc.swagger.json @@ -636,6 +636,33 @@ ] } }, + "/v3alpha/kv/lease/timetolive": { + "post": { + "summary": "LeaseTimeToLive retrieves lease information.", + "operationId": "LeaseTimeToLive", + "responses": { + "200": { + "description": "", + "schema": { + "$ref": "#/definitions/etcdserverpbLeaseTimeToLiveResponse" + } + } + }, + "parameters": [ + { + "name": "body", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/etcdserverpbLeaseTimeToLiveRequest" + } + } + ], + "tags": [ + "Lease" + ] + } + }, "/v3alpha/kv/put": { "post": { "summary": "Put puts the given key into the key-value store.\nA put request increments the revision of the key-value store\nand generates one event in the event history.", @@ -1614,6 +1641,52 @@ } } }, + "etcdserverpbLeaseTimeToLiveRequest": { + "type": "object", + "properties": { + "ID": { + "type": "string", + "format": "int64", + "description": "ID is the lease ID for the lease." + }, + "keys": { + "type": "boolean", + "format": "boolean", + "description": "keys is true to query all the keys attached to this lease." + } + } + }, + "etcdserverpbLeaseTimeToLiveResponse": { + "type": "object", + "properties": { + "ID": { + "type": "string", + "format": "int64", + "description": "ID is the lease ID from the keep alive request." + }, + "TTL": { + "type": "string", + "format": "int64", + "description": "TTL is the remaining TTL in seconds for the lease; the lease will expire in under TTL+1 seconds." + }, + "grantedTTL": { + "type": "string", + "format": "int64", + "description": "GrantedTTL is the initial granted time in seconds upon lease creation/renewal." + }, + "header": { + "$ref": "#/definitions/etcdserverpbResponseHeader" + }, + "keys": { + "type": "array", + "items": { + "type": "string", + "format": "byte" + }, + "description": "Keys is the list of keys attached to this lease." + } + } + }, "etcdserverpbMember": { "type": "object", "properties": { diff --git a/clientv3/integration/lease_test.go b/clientv3/integration/lease_test.go index 00a21e371..7f4c20efd 100644 --- a/clientv3/integration/lease_test.go +++ b/clientv3/integration/lease_test.go @@ -15,6 +15,8 @@ package integration import ( + "reflect" + "sort" "testing" "time" @@ -455,3 +457,56 @@ func TestLeaseKeepAliveTTLTimeout(t *testing.T) { clus.Members[0].Restart(t) } + +func TestLeaseTimeToLive(t *testing.T) { + defer testutil.AfterTest(t) + + clus := integration.NewClusterV3(t, &integration.ClusterConfig{Size: 3}) + defer clus.Terminate(t) + + lapi := clientv3.NewLease(clus.RandClient()) + defer lapi.Close() + + resp, err := lapi.Grant(context.Background(), 10) + if err != nil { + t.Errorf("failed to create lease %v", err) + } + + kv := clientv3.NewKV(clus.RandClient()) + keys := []string{"foo1", "foo2"} + for i := range keys { + if _, err = kv.Put(context.TODO(), keys[i], "bar", clientv3.WithLease(resp.ID)); err != nil { + t.Fatal(err) + } + } + + lresp, lerr := lapi.TimeToLive(context.Background(), resp.ID, clientv3.WithAttachedKeys()) + if lerr != nil { + t.Fatal(lerr) + } + if lresp.ID != resp.ID { + t.Fatalf("leaseID expected %d, got %d", resp.ID, lresp.ID) + } + if lresp.GrantedTTL != int64(10) { + t.Fatalf("GrantedTTL expected %d, got %d", 10, lresp.GrantedTTL) + } + if lresp.TTL == 0 || lresp.TTL > lresp.GrantedTTL { + t.Fatalf("unexpected TTL %d (granted %d)", lresp.TTL, lresp.GrantedTTL) + } + ks := make([]string, len(lresp.Keys)) + for i := range lresp.Keys { + ks[i] = string(lresp.Keys[i]) + } + sort.Strings(ks) + if !reflect.DeepEqual(ks, keys) { + t.Fatalf("keys expected %v, got %v", keys, ks) + } + + lresp, lerr = lapi.TimeToLive(context.Background(), resp.ID) + if lerr != nil { + t.Fatal(lerr) + } + if len(lresp.Keys) != 0 { + t.Fatalf("unexpected keys %+v", lresp.Keys) + } +} diff --git a/clientv3/lease.go b/clientv3/lease.go index ae2a136dd..ed8bb0a53 100644 --- a/clientv3/lease.go +++ b/clientv3/lease.go @@ -44,6 +44,21 @@ type LeaseKeepAliveResponse struct { TTL int64 } +// LeaseTimeToLiveResponse is used to convert the protobuf lease timetolive response. +type LeaseTimeToLiveResponse struct { + *pb.ResponseHeader + ID LeaseID `json:"id"` + + // TTL is the remaining TTL in seconds for the lease; the lease will expire in under TTL+1 seconds. + TTL int64 `json:"ttl"` + + // GrantedTTL is the initial granted time in seconds upon lease creation/renewal. + GrantedTTL int64 `json:"granted-ttl"` + + // Keys is the list of keys attached to this lease. + Keys [][]byte `json:"keys"` +} + const ( // defaultTTL is the assumed lease TTL used for the first keepalive // deadline before the actual TTL is known to the client. @@ -61,6 +76,9 @@ type Lease interface { // Revoke revokes the given lease. Revoke(ctx context.Context, id LeaseID) (*LeaseRevokeResponse, error) + // TimeToLive retrieves the lease information of the given lease ID. + TimeToLive(ctx context.Context, id LeaseID, opts ...LeaseOption) (*LeaseTimeToLiveResponse, error) + // KeepAlive keeps the given lease alive forever. KeepAlive(ctx context.Context, id LeaseID) (<-chan *LeaseKeepAliveResponse, error) @@ -170,6 +188,30 @@ func (l *lessor) Revoke(ctx context.Context, id LeaseID) (*LeaseRevokeResponse, } } +func (l *lessor) TimeToLive(ctx context.Context, id LeaseID, opts ...LeaseOption) (*LeaseTimeToLiveResponse, error) { + cctx, cancel := context.WithCancel(ctx) + done := cancelWhenStop(cancel, l.stopCtx.Done()) + defer close(done) + + for { + r := toLeaseTimeToLiveRequest(id, opts...) + resp, err := l.remote.LeaseTimeToLive(cctx, r) + if err == nil { + gresp := &LeaseTimeToLiveResponse{ + ResponseHeader: resp.GetHeader(), + ID: LeaseID(resp.ID), + TTL: resp.TTL, + GrantedTTL: resp.GrantedTTL, + Keys: resp.Keys, + } + return gresp, nil + } + if isHaltErr(cctx, err) { + return nil, toErr(cctx, err) + } + } +} + func (l *lessor) KeepAlive(ctx context.Context, id LeaseID) (<-chan *LeaseKeepAliveResponse, error) { ch := make(chan *LeaseKeepAliveResponse, leaseResponseChSize) diff --git a/clientv3/op.go b/clientv3/op.go index cadea1f8e..e5796849a 100644 --- a/clientv3/op.go +++ b/clientv3/op.go @@ -83,7 +83,6 @@ func (op Op) toRequestOp() *pb.RequestOp { return &pb.RequestOp{Request: &pb.RequestOp_RequestPut{RequestPut: r}} case tDeleteRange: r := &pb.DeleteRangeRequest{Key: op.key, RangeEnd: op.end, PrevKv: op.prevKV} - return &pb.RequestOp{Request: &pb.RequestOp_RequestDeleteRange{RequestDeleteRange: r}} default: panic("Unknown Op") @@ -320,3 +319,32 @@ func WithPrevKV() OpOption { op.prevKV = true } } + +// LeaseOp represents an Operation that lease can execute. +type LeaseOp struct { + id LeaseID + + // for TimeToLive + attachedKeys bool +} + +// LeaseOption configures lease operations. +type LeaseOption func(*LeaseOp) + +func (op *LeaseOp) applyOpts(opts []LeaseOption) { + for _, opt := range opts { + opt(op) + } +} + +// WithAttachedKeys requests lease timetolive API to return +// attached keys of given lease ID. +func WithAttachedKeys() LeaseOption { + return func(op *LeaseOp) { op.attachedKeys = true } +} + +func toLeaseTimeToLiveRequest(id LeaseID, opts ...LeaseOption) *pb.LeaseTimeToLiveRequest { + ret := &LeaseOp{id: id} + ret.applyOpts(opts) + return &pb.LeaseTimeToLiveRequest{ID: int64(id), Keys: ret.attachedKeys} +} diff --git a/e2e/ctl_v3_lease_test.go b/e2e/ctl_v3_lease_test.go index 20936ae08..d27060a64 100644 --- a/e2e/ctl_v3_lease_test.go +++ b/e2e/ctl_v3_lease_test.go @@ -21,8 +21,35 @@ import ( "testing" ) -func TestCtlV3LeaseKeepAlive(t *testing.T) { testCtl(t, leaseTestKeepAlive) } -func TestCtlV3LeaseRevoke(t *testing.T) { testCtl(t, leaseTestRevoke) } +func TestCtlV3LeaseGrantTimeToLive(t *testing.T) { testCtl(t, leaseTestGrantTimeToLive) } +func TestCtlV3LeaseKeepAlive(t *testing.T) { testCtl(t, leaseTestKeepAlive) } +func TestCtlV3LeaseRevoke(t *testing.T) { testCtl(t, leaseTestRevoke) } + +func leaseTestGrantTimeToLive(cx ctlCtx) { + id, err := ctlV3LeaseGrant(cx, 10) + if err != nil { + cx.t.Fatal(err) + } + + cmdArgs := append(cx.PrefixArgs(), "lease", "timetolive", id, "--keys") + proc, err := spawnCmd(cmdArgs) + if err != nil { + cx.t.Fatal(err) + } + line, err := proc.Expect(" granted with TTL(") + if err != nil { + cx.t.Fatal(err) + } + if err = proc.Close(); err != nil { + cx.t.Fatal(err) + } + if !strings.Contains(line, ", attached keys") { + cx.t.Fatalf("expected 'attached keys', got %q", line) + } + if !strings.Contains(line, id) { + cx.t.Fatalf("expected leaseID %q, got %q", id, line) + } +} func leaseTestKeepAlive(cx ctlCtx) { // put with TTL 10 seconds and keep-alive diff --git a/etcdctl/README.md b/etcdctl/README.md index c9202dbee..5465f6eb6 100644 --- a/etcdctl/README.md +++ b/etcdctl/README.md @@ -326,6 +326,40 @@ LEASE REVOKE destroys a given lease, deleting all attached keys. lease 32695410dcc0ca06 revoked ``` + +### LEASE TIMETOLIVE \ + +LEASE TIMETOLIVE retrieves the lease information with the given lease ID. + +#### Return value + +- On success, prints lease information. + +- On failure, prints an error message and returns with a non-zero exit code. + +#### Example + +```bash +./etcdctl lease grant 500 +lease 2d8257079fa1bc0c granted with TTL(500s) + +./etcdctl put foo1 bar --lease=2d8257079fa1bc0c +./etcdctl put foo2 bar --lease=2d8257079fa1bc0c + +./etcdctl lease timetolive 2d8257079fa1bc0c +lease 2d8257079fa1bc0c granted with TTL(500s), remaining(481s) + +./etcdctl lease timetolive 2d8257079fa1bc0c --keys +lease 2d8257079fa1bc0c granted with TTL(500s), remaining(472s), attached keys([foo2 foo1]) + +./etcdctl lease timetolive 2d8257079fa1bc0c --write-out=json +{"cluster_id":17186838941855831277,"member_id":4845372305070271874,"revision":3,"raft_term":2,"id":3279279168933706764,"ttl":465,"granted-ttl":500,"keys":null} + +./etcdctl lease timetolive 2d8257079fa1bc0c --write-out=json --keys +{"cluster_id":17186838941855831277,"member_id":4845372305070271874,"revision":3,"raft_term":2,"id":3279279168933706764,"ttl":459,"granted-ttl":500,"keys":["Zm9vMQ==","Zm9vMg=="]} +``` + + ### LEASE KEEP-ALIVE \ LEASE KEEP-ALIVE periodically refreshes a lease so it does not expire. diff --git a/etcdctl/ctlv3/command/lease_command.go b/etcdctl/ctlv3/command/lease_command.go index fb07cf059..0a72d9e8b 100644 --- a/etcdctl/ctlv3/command/lease_command.go +++ b/etcdctl/ctlv3/command/lease_command.go @@ -32,6 +32,7 @@ func NewLeaseCommand() *cobra.Command { lc.AddCommand(NewLeaseGrantCommand()) lc.AddCommand(NewLeaseRevokeCommand()) + lc.AddCommand(NewLeaseTimeToLiveCommand()) lc.AddCommand(NewLeaseKeepAliveCommand()) return lc @@ -87,13 +88,9 @@ func leaseRevokeCommandFunc(cmd *cobra.Command, args []string) { ExitWithError(ExitBadArgs, fmt.Errorf("lease revoke command needs 1 argument")) } - id, err := strconv.ParseInt(args[0], 16, 64) - if err != nil { - ExitWithError(ExitBadArgs, fmt.Errorf("bad lease ID arg (%v), expecting ID in Hex", err)) - } - + id := leaseFromArgs(args[0]) ctx, cancel := commandCtx(cmd) - _, err = mustClientFromCmd(cmd).Revoke(ctx, v3.LeaseID(id)) + _, err := mustClientFromCmd(cmd).Revoke(ctx, id) cancel() if err != nil { ExitWithError(ExitError, fmt.Errorf("failed to revoke lease (%v)\n", err)) @@ -101,6 +98,37 @@ func leaseRevokeCommandFunc(cmd *cobra.Command, args []string) { fmt.Printf("lease %016x revoked\n", id) } +var timeToLiveKeys bool + +// NewLeaseTimeToLiveCommand returns the cobra command for "lease timetolive". +func NewLeaseTimeToLiveCommand() *cobra.Command { + lc := &cobra.Command{ + Use: "timetolive ", + Short: "Get lease information", + + Run: leaseTimeToLiveCommandFunc, + } + lc.Flags().BoolVar(&timeToLiveKeys, "keys", false, "Get keys attached to this lease") + + return lc +} + +// leaseTimeToLiveCommandFunc executes the "lease timetolive" command. +func leaseTimeToLiveCommandFunc(cmd *cobra.Command, args []string) { + if len(args) != 1 { + ExitWithError(ExitBadArgs, fmt.Errorf("lease timetolive command needs lease ID as argument")) + } + var opts []v3.LeaseOption + if timeToLiveKeys { + opts = append(opts, v3.WithAttachedKeys()) + } + resp, rerr := mustClientFromCmd(cmd).TimeToLive(context.TODO(), leaseFromArgs(args[0]), opts...) + if rerr != nil { + ExitWithError(ExitBadConnection, rerr) + } + display.TimeToLive(*resp, timeToLiveKeys) +} + // NewLeaseKeepAliveCommand returns the cobra command for "lease keep-alive". func NewLeaseKeepAliveCommand() *cobra.Command { lc := &cobra.Command{ @@ -119,12 +147,8 @@ func leaseKeepAliveCommandFunc(cmd *cobra.Command, args []string) { ExitWithError(ExitBadArgs, fmt.Errorf("lease keep-alive command needs lease ID as argument")) } - id, err := strconv.ParseInt(args[0], 16, 64) - if err != nil { - ExitWithError(ExitBadArgs, fmt.Errorf("bad lease ID arg (%v), expecting ID in Hex", err)) - } - - respc, kerr := mustClientFromCmd(cmd).KeepAlive(context.TODO(), v3.LeaseID(id)) + id := leaseFromArgs(args[0]) + respc, kerr := mustClientFromCmd(cmd).KeepAlive(context.TODO(), id) if kerr != nil { ExitWithError(ExitBadConnection, kerr) } @@ -134,3 +158,11 @@ func leaseKeepAliveCommandFunc(cmd *cobra.Command, args []string) { } fmt.Printf("lease %016x expired or revoked.\n", id) } + +func leaseFromArgs(arg string) v3.LeaseID { + id, err := strconv.ParseInt(arg, 16, 64) + if err != nil { + ExitWithError(ExitBadArgs, fmt.Errorf("bad lease ID arg (%v), expecting ID in Hex", err)) + } + return v3.LeaseID(id) +} diff --git a/etcdctl/ctlv3/command/printer.go b/etcdctl/ctlv3/command/printer.go index 2be8aad2e..de35be86c 100644 --- a/etcdctl/ctlv3/command/printer.go +++ b/etcdctl/ctlv3/command/printer.go @@ -35,6 +35,8 @@ type printer interface { Txn(v3.TxnResponse) Watch(v3.WatchResponse) + TimeToLive(r v3.LeaseTimeToLiveResponse, keys bool) + MemberList(v3.MemberListResponse) EndpointStatus([]epStatus) @@ -159,6 +161,18 @@ func (s *simplePrinter) Watch(resp v3.WatchResponse) { } } +func (s *simplePrinter) TimeToLive(resp v3.LeaseTimeToLiveResponse, keys bool) { + txt := fmt.Sprintf("lease %016x granted with TTL(%ds), remaining(%ds)", resp.ID, resp.GrantedTTL, resp.TTL) + if keys { + ks := make([]string, len(resp.Keys)) + for i := range resp.Keys { + ks[i] = string(resp.Keys[i]) + } + txt += fmt.Sprintf(", attached keys(%v)", ks) + } + fmt.Println(txt) +} + func (s *simplePrinter) Alarm(resp v3.AlarmResponse) { for _, e := range resp.Alarms { fmt.Printf("%+v\n", e) @@ -203,6 +217,9 @@ func (tp *tablePrinter) Txn(r v3.TxnResponse) { func (tp *tablePrinter) Watch(r v3.WatchResponse) { ExitWithError(ExitBadFeature, errors.New("table is not supported as output format")) } +func (tp *tablePrinter) TimeToLive(r v3.LeaseTimeToLiveResponse, keys bool) { + ExitWithError(ExitBadFeature, errors.New("table is not supported as output format")) +} func (tp *tablePrinter) Alarm(r v3.AlarmResponse) { ExitWithError(ExitBadFeature, errors.New("table is not supported as output format")) } @@ -236,15 +253,16 @@ func (tp *tablePrinter) DBStatus(r dbstatus) { type jsonPrinter struct{} -func (p *jsonPrinter) Del(r v3.DeleteResponse) { printJSON(r) } -func (p *jsonPrinter) Get(r v3.GetResponse) { printJSON(r) } -func (p *jsonPrinter) Put(r v3.PutResponse) { printJSON(r) } -func (p *jsonPrinter) Txn(r v3.TxnResponse) { printJSON(r) } -func (p *jsonPrinter) Watch(r v3.WatchResponse) { printJSON(r) } -func (p *jsonPrinter) Alarm(r v3.AlarmResponse) { printJSON(r) } -func (p *jsonPrinter) MemberList(r v3.MemberListResponse) { printJSON(r) } -func (p *jsonPrinter) EndpointStatus(r []epStatus) { printJSON(r) } -func (p *jsonPrinter) DBStatus(r dbstatus) { printJSON(r) } +func (p *jsonPrinter) Del(r v3.DeleteResponse) { printJSON(r) } +func (p *jsonPrinter) Get(r v3.GetResponse) { printJSON(r) } +func (p *jsonPrinter) Put(r v3.PutResponse) { printJSON(r) } +func (p *jsonPrinter) Txn(r v3.TxnResponse) { printJSON(r) } +func (p *jsonPrinter) Watch(r v3.WatchResponse) { printJSON(r) } +func (p *jsonPrinter) TimeToLive(r v3.LeaseTimeToLiveResponse, keys bool) { printJSON(r) } +func (p *jsonPrinter) Alarm(r v3.AlarmResponse) { printJSON(r) } +func (p *jsonPrinter) MemberList(r v3.MemberListResponse) { printJSON(r) } +func (p *jsonPrinter) EndpointStatus(r []epStatus) { printJSON(r) } +func (p *jsonPrinter) DBStatus(r dbstatus) { printJSON(r) } func printJSON(v interface{}) { b, err := json.Marshal(v) @@ -283,6 +301,10 @@ func (p *pbPrinter) Watch(r v3.WatchResponse) { } } +func (p *pbPrinter) TimeToLive(r v3.LeaseTimeToLiveResponse, keys bool) { + ExitWithError(ExitBadFeature, errors.New("only support simple or json as output format")) +} + func (p *pbPrinter) Alarm(r v3.AlarmResponse) { printPB((*pb.AlarmResponse)(&r)) } diff --git a/etcdserver/api/v2http/peer.go b/etcdserver/api/v2http/peer.go index e8fa3b60a..456fa4619 100644 --- a/etcdserver/api/v2http/peer.go +++ b/etcdserver/api/v2http/peer.go @@ -26,7 +26,6 @@ import ( const ( peerMembersPrefix = "/members" - leasesPrefix = "/leases" ) // NewPeerHandler generates an http.Handler to handle etcd peer requests. @@ -49,7 +48,8 @@ func newPeerHandler(cluster api.Cluster, raftHandler http.Handler, leaseHandler mux.Handle(rafthttp.RaftPrefix+"/", raftHandler) mux.Handle(peerMembersPrefix, mh) if leaseHandler != nil { - mux.Handle(leasesPrefix, leaseHandler) + mux.Handle(leasehttp.LeasePrefix, leaseHandler) + mux.Handle(leasehttp.LeaseInternalPrefix, leaseHandler) } mux.HandleFunc(versionPath, versionHandler(cluster, serveVersion)) return mux diff --git a/etcdserver/api/v3rpc/lease.go b/etcdserver/api/v3rpc/lease.go index 108e1387a..0ebffadb4 100644 --- a/etcdserver/api/v3rpc/lease.go +++ b/etcdserver/api/v3rpc/lease.go @@ -54,6 +54,15 @@ func (ls *LeaseServer) LeaseRevoke(ctx context.Context, rr *pb.LeaseRevokeReques return resp, nil } +func (ls *LeaseServer) LeaseTimeToLive(ctx context.Context, rr *pb.LeaseTimeToLiveRequest) (*pb.LeaseTimeToLiveResponse, error) { + resp, err := ls.le.LeaseTimeToLive(ctx, rr) + if err != nil { + return nil, rpctypes.ErrGRPCLeaseNotFound + } + ls.hdr.fill(resp.Header) + return resp, nil +} + func (ls *LeaseServer) LeaseKeepAlive(stream pb.Lease_LeaseKeepAliveServer) error { for { req, err := stream.Recv() diff --git a/etcdserver/etcdserverpb/etcdserver.pb.go b/etcdserver/etcdserverpb/etcdserver.pb.go index 746e9a116..a97bb1d62 100644 --- a/etcdserver/etcdserverpb/etcdserver.pb.go +++ b/etcdserver/etcdserverpb/etcdserver.pb.go @@ -45,6 +45,8 @@ LeaseRevokeResponse LeaseKeepAliveRequest LeaseKeepAliveResponse + LeaseTimeToLiveRequest + LeaseTimeToLiveResponse Member MemberAddRequest MemberAddResponse diff --git a/etcdserver/etcdserverpb/rpc.pb.go b/etcdserver/etcdserverpb/rpc.pb.go index afb1d606f..8c0bf44f3 100644 --- a/etcdserver/etcdserverpb/rpc.pb.go +++ b/etcdserver/etcdserverpb/rpc.pb.go @@ -202,7 +202,7 @@ func (x AlarmRequest_AlarmAction) String() string { return proto.EnumName(AlarmRequest_AlarmAction_name, int32(x)) } func (AlarmRequest_AlarmAction) EnumDescriptor() ([]byte, []int) { - return fileDescriptorRpc, []int{39, 0} + return fileDescriptorRpc, []int{41, 0} } type ResponseHeader struct { @@ -1322,6 +1322,42 @@ func (m *LeaseKeepAliveResponse) GetHeader() *ResponseHeader { return nil } +type LeaseTimeToLiveRequest struct { + // ID is the lease ID for the lease. + ID int64 `protobuf:"varint,1,opt,name=ID,json=iD,proto3" json:"ID,omitempty"` + // keys is true to query all the keys attached to this lease. + Keys bool `protobuf:"varint,2,opt,name=keys,proto3" json:"keys,omitempty"` +} + +func (m *LeaseTimeToLiveRequest) Reset() { *m = LeaseTimeToLiveRequest{} } +func (m *LeaseTimeToLiveRequest) String() string { return proto.CompactTextString(m) } +func (*LeaseTimeToLiveRequest) ProtoMessage() {} +func (*LeaseTimeToLiveRequest) Descriptor() ([]byte, []int) { return fileDescriptorRpc, []int{28} } + +type LeaseTimeToLiveResponse struct { + Header *ResponseHeader `protobuf:"bytes,1,opt,name=header" json:"header,omitempty"` + // ID is the lease ID from the keep alive request. + ID int64 `protobuf:"varint,2,opt,name=ID,json=iD,proto3" json:"ID,omitempty"` + // TTL is the remaining TTL in seconds for the lease; the lease will expire in under TTL+1 seconds. + TTL int64 `protobuf:"varint,3,opt,name=TTL,json=tTL,proto3" json:"TTL,omitempty"` + // GrantedTTL is the initial granted time in seconds upon lease creation/renewal. + GrantedTTL int64 `protobuf:"varint,4,opt,name=grantedTTL,proto3" json:"grantedTTL,omitempty"` + // Keys is the list of keys attached to this lease. + Keys [][]byte `protobuf:"bytes,5,rep,name=keys" json:"keys,omitempty"` +} + +func (m *LeaseTimeToLiveResponse) Reset() { *m = LeaseTimeToLiveResponse{} } +func (m *LeaseTimeToLiveResponse) String() string { return proto.CompactTextString(m) } +func (*LeaseTimeToLiveResponse) ProtoMessage() {} +func (*LeaseTimeToLiveResponse) Descriptor() ([]byte, []int) { return fileDescriptorRpc, []int{29} } + +func (m *LeaseTimeToLiveResponse) GetHeader() *ResponseHeader { + if m != nil { + return m.Header + } + return nil +} + type Member struct { // ID is the member ID for this member. ID uint64 `protobuf:"varint,1,opt,name=ID,json=iD,proto3" json:"ID,omitempty"` @@ -1336,7 +1372,7 @@ type Member struct { func (m *Member) Reset() { *m = Member{} } func (m *Member) String() string { return proto.CompactTextString(m) } func (*Member) ProtoMessage() {} -func (*Member) Descriptor() ([]byte, []int) { return fileDescriptorRpc, []int{28} } +func (*Member) Descriptor() ([]byte, []int) { return fileDescriptorRpc, []int{30} } type MemberAddRequest struct { // peerURLs is the list of URLs the added member will use to communicate with the cluster. @@ -1346,7 +1382,7 @@ type MemberAddRequest struct { func (m *MemberAddRequest) Reset() { *m = MemberAddRequest{} } func (m *MemberAddRequest) String() string { return proto.CompactTextString(m) } func (*MemberAddRequest) ProtoMessage() {} -func (*MemberAddRequest) Descriptor() ([]byte, []int) { return fileDescriptorRpc, []int{29} } +func (*MemberAddRequest) Descriptor() ([]byte, []int) { return fileDescriptorRpc, []int{31} } type MemberAddResponse struct { Header *ResponseHeader `protobuf:"bytes,1,opt,name=header" json:"header,omitempty"` @@ -1357,7 +1393,7 @@ type MemberAddResponse struct { func (m *MemberAddResponse) Reset() { *m = MemberAddResponse{} } func (m *MemberAddResponse) String() string { return proto.CompactTextString(m) } func (*MemberAddResponse) ProtoMessage() {} -func (*MemberAddResponse) Descriptor() ([]byte, []int) { return fileDescriptorRpc, []int{30} } +func (*MemberAddResponse) Descriptor() ([]byte, []int) { return fileDescriptorRpc, []int{32} } func (m *MemberAddResponse) GetHeader() *ResponseHeader { if m != nil { @@ -1381,7 +1417,7 @@ type MemberRemoveRequest struct { func (m *MemberRemoveRequest) Reset() { *m = MemberRemoveRequest{} } func (m *MemberRemoveRequest) String() string { return proto.CompactTextString(m) } func (*MemberRemoveRequest) ProtoMessage() {} -func (*MemberRemoveRequest) Descriptor() ([]byte, []int) { return fileDescriptorRpc, []int{31} } +func (*MemberRemoveRequest) Descriptor() ([]byte, []int) { return fileDescriptorRpc, []int{33} } type MemberRemoveResponse struct { Header *ResponseHeader `protobuf:"bytes,1,opt,name=header" json:"header,omitempty"` @@ -1390,7 +1426,7 @@ type MemberRemoveResponse struct { func (m *MemberRemoveResponse) Reset() { *m = MemberRemoveResponse{} } func (m *MemberRemoveResponse) String() string { return proto.CompactTextString(m) } func (*MemberRemoveResponse) ProtoMessage() {} -func (*MemberRemoveResponse) Descriptor() ([]byte, []int) { return fileDescriptorRpc, []int{32} } +func (*MemberRemoveResponse) Descriptor() ([]byte, []int) { return fileDescriptorRpc, []int{34} } func (m *MemberRemoveResponse) GetHeader() *ResponseHeader { if m != nil { @@ -1409,7 +1445,7 @@ type MemberUpdateRequest struct { func (m *MemberUpdateRequest) Reset() { *m = MemberUpdateRequest{} } func (m *MemberUpdateRequest) String() string { return proto.CompactTextString(m) } func (*MemberUpdateRequest) ProtoMessage() {} -func (*MemberUpdateRequest) Descriptor() ([]byte, []int) { return fileDescriptorRpc, []int{33} } +func (*MemberUpdateRequest) Descriptor() ([]byte, []int) { return fileDescriptorRpc, []int{35} } type MemberUpdateResponse struct { Header *ResponseHeader `protobuf:"bytes,1,opt,name=header" json:"header,omitempty"` @@ -1418,7 +1454,7 @@ type MemberUpdateResponse struct { func (m *MemberUpdateResponse) Reset() { *m = MemberUpdateResponse{} } func (m *MemberUpdateResponse) String() string { return proto.CompactTextString(m) } func (*MemberUpdateResponse) ProtoMessage() {} -func (*MemberUpdateResponse) Descriptor() ([]byte, []int) { return fileDescriptorRpc, []int{34} } +func (*MemberUpdateResponse) Descriptor() ([]byte, []int) { return fileDescriptorRpc, []int{36} } func (m *MemberUpdateResponse) GetHeader() *ResponseHeader { if m != nil { @@ -1433,7 +1469,7 @@ type MemberListRequest struct { func (m *MemberListRequest) Reset() { *m = MemberListRequest{} } func (m *MemberListRequest) String() string { return proto.CompactTextString(m) } func (*MemberListRequest) ProtoMessage() {} -func (*MemberListRequest) Descriptor() ([]byte, []int) { return fileDescriptorRpc, []int{35} } +func (*MemberListRequest) Descriptor() ([]byte, []int) { return fileDescriptorRpc, []int{37} } type MemberListResponse struct { Header *ResponseHeader `protobuf:"bytes,1,opt,name=header" json:"header,omitempty"` @@ -1444,7 +1480,7 @@ type MemberListResponse struct { func (m *MemberListResponse) Reset() { *m = MemberListResponse{} } func (m *MemberListResponse) String() string { return proto.CompactTextString(m) } func (*MemberListResponse) ProtoMessage() {} -func (*MemberListResponse) Descriptor() ([]byte, []int) { return fileDescriptorRpc, []int{36} } +func (*MemberListResponse) Descriptor() ([]byte, []int) { return fileDescriptorRpc, []int{38} } func (m *MemberListResponse) GetHeader() *ResponseHeader { if m != nil { @@ -1466,7 +1502,7 @@ type DefragmentRequest struct { func (m *DefragmentRequest) Reset() { *m = DefragmentRequest{} } func (m *DefragmentRequest) String() string { return proto.CompactTextString(m) } func (*DefragmentRequest) ProtoMessage() {} -func (*DefragmentRequest) Descriptor() ([]byte, []int) { return fileDescriptorRpc, []int{37} } +func (*DefragmentRequest) Descriptor() ([]byte, []int) { return fileDescriptorRpc, []int{39} } type DefragmentResponse struct { Header *ResponseHeader `protobuf:"bytes,1,opt,name=header" json:"header,omitempty"` @@ -1475,7 +1511,7 @@ type DefragmentResponse struct { func (m *DefragmentResponse) Reset() { *m = DefragmentResponse{} } func (m *DefragmentResponse) String() string { return proto.CompactTextString(m) } func (*DefragmentResponse) ProtoMessage() {} -func (*DefragmentResponse) Descriptor() ([]byte, []int) { return fileDescriptorRpc, []int{38} } +func (*DefragmentResponse) Descriptor() ([]byte, []int) { return fileDescriptorRpc, []int{40} } func (m *DefragmentResponse) GetHeader() *ResponseHeader { if m != nil { @@ -1499,7 +1535,7 @@ type AlarmRequest struct { func (m *AlarmRequest) Reset() { *m = AlarmRequest{} } func (m *AlarmRequest) String() string { return proto.CompactTextString(m) } func (*AlarmRequest) ProtoMessage() {} -func (*AlarmRequest) Descriptor() ([]byte, []int) { return fileDescriptorRpc, []int{39} } +func (*AlarmRequest) Descriptor() ([]byte, []int) { return fileDescriptorRpc, []int{41} } type AlarmMember struct { // memberID is the ID of the member associated with the raised alarm. @@ -1511,7 +1547,7 @@ type AlarmMember struct { func (m *AlarmMember) Reset() { *m = AlarmMember{} } func (m *AlarmMember) String() string { return proto.CompactTextString(m) } func (*AlarmMember) ProtoMessage() {} -func (*AlarmMember) Descriptor() ([]byte, []int) { return fileDescriptorRpc, []int{40} } +func (*AlarmMember) Descriptor() ([]byte, []int) { return fileDescriptorRpc, []int{42} } type AlarmResponse struct { Header *ResponseHeader `protobuf:"bytes,1,opt,name=header" json:"header,omitempty"` @@ -1522,7 +1558,7 @@ type AlarmResponse struct { func (m *AlarmResponse) Reset() { *m = AlarmResponse{} } func (m *AlarmResponse) String() string { return proto.CompactTextString(m) } func (*AlarmResponse) ProtoMessage() {} -func (*AlarmResponse) Descriptor() ([]byte, []int) { return fileDescriptorRpc, []int{41} } +func (*AlarmResponse) Descriptor() ([]byte, []int) { return fileDescriptorRpc, []int{43} } func (m *AlarmResponse) GetHeader() *ResponseHeader { if m != nil { @@ -1544,7 +1580,7 @@ type StatusRequest struct { func (m *StatusRequest) Reset() { *m = StatusRequest{} } func (m *StatusRequest) String() string { return proto.CompactTextString(m) } func (*StatusRequest) ProtoMessage() {} -func (*StatusRequest) Descriptor() ([]byte, []int) { return fileDescriptorRpc, []int{42} } +func (*StatusRequest) Descriptor() ([]byte, []int) { return fileDescriptorRpc, []int{44} } type StatusResponse struct { Header *ResponseHeader `protobuf:"bytes,1,opt,name=header" json:"header,omitempty"` @@ -1563,7 +1599,7 @@ type StatusResponse struct { func (m *StatusResponse) Reset() { *m = StatusResponse{} } func (m *StatusResponse) String() string { return proto.CompactTextString(m) } func (*StatusResponse) ProtoMessage() {} -func (*StatusResponse) Descriptor() ([]byte, []int) { return fileDescriptorRpc, []int{43} } +func (*StatusResponse) Descriptor() ([]byte, []int) { return fileDescriptorRpc, []int{45} } func (m *StatusResponse) GetHeader() *ResponseHeader { if m != nil { @@ -1578,7 +1614,7 @@ type AuthEnableRequest struct { func (m *AuthEnableRequest) Reset() { *m = AuthEnableRequest{} } func (m *AuthEnableRequest) String() string { return proto.CompactTextString(m) } func (*AuthEnableRequest) ProtoMessage() {} -func (*AuthEnableRequest) Descriptor() ([]byte, []int) { return fileDescriptorRpc, []int{44} } +func (*AuthEnableRequest) Descriptor() ([]byte, []int) { return fileDescriptorRpc, []int{46} } type AuthDisableRequest struct { } @@ -1586,7 +1622,7 @@ type AuthDisableRequest struct { func (m *AuthDisableRequest) Reset() { *m = AuthDisableRequest{} } func (m *AuthDisableRequest) String() string { return proto.CompactTextString(m) } func (*AuthDisableRequest) ProtoMessage() {} -func (*AuthDisableRequest) Descriptor() ([]byte, []int) { return fileDescriptorRpc, []int{45} } +func (*AuthDisableRequest) Descriptor() ([]byte, []int) { return fileDescriptorRpc, []int{47} } type AuthenticateRequest struct { Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"` @@ -1596,7 +1632,7 @@ type AuthenticateRequest struct { func (m *AuthenticateRequest) Reset() { *m = AuthenticateRequest{} } func (m *AuthenticateRequest) String() string { return proto.CompactTextString(m) } func (*AuthenticateRequest) ProtoMessage() {} -func (*AuthenticateRequest) Descriptor() ([]byte, []int) { return fileDescriptorRpc, []int{46} } +func (*AuthenticateRequest) Descriptor() ([]byte, []int) { return fileDescriptorRpc, []int{48} } type AuthUserAddRequest struct { Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"` @@ -1606,7 +1642,7 @@ type AuthUserAddRequest struct { func (m *AuthUserAddRequest) Reset() { *m = AuthUserAddRequest{} } func (m *AuthUserAddRequest) String() string { return proto.CompactTextString(m) } func (*AuthUserAddRequest) ProtoMessage() {} -func (*AuthUserAddRequest) Descriptor() ([]byte, []int) { return fileDescriptorRpc, []int{47} } +func (*AuthUserAddRequest) Descriptor() ([]byte, []int) { return fileDescriptorRpc, []int{49} } type AuthUserGetRequest struct { Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"` @@ -1615,7 +1651,7 @@ type AuthUserGetRequest struct { func (m *AuthUserGetRequest) Reset() { *m = AuthUserGetRequest{} } func (m *AuthUserGetRequest) String() string { return proto.CompactTextString(m) } func (*AuthUserGetRequest) ProtoMessage() {} -func (*AuthUserGetRequest) Descriptor() ([]byte, []int) { return fileDescriptorRpc, []int{48} } +func (*AuthUserGetRequest) Descriptor() ([]byte, []int) { return fileDescriptorRpc, []int{50} } type AuthUserDeleteRequest struct { // name is the name of the user to delete. @@ -1625,7 +1661,7 @@ type AuthUserDeleteRequest struct { func (m *AuthUserDeleteRequest) Reset() { *m = AuthUserDeleteRequest{} } func (m *AuthUserDeleteRequest) String() string { return proto.CompactTextString(m) } func (*AuthUserDeleteRequest) ProtoMessage() {} -func (*AuthUserDeleteRequest) Descriptor() ([]byte, []int) { return fileDescriptorRpc, []int{49} } +func (*AuthUserDeleteRequest) Descriptor() ([]byte, []int) { return fileDescriptorRpc, []int{51} } type AuthUserChangePasswordRequest struct { // name is the name of the user whose password is being changed. @@ -1638,7 +1674,7 @@ func (m *AuthUserChangePasswordRequest) Reset() { *m = AuthUserChangePas func (m *AuthUserChangePasswordRequest) String() string { return proto.CompactTextString(m) } func (*AuthUserChangePasswordRequest) ProtoMessage() {} func (*AuthUserChangePasswordRequest) Descriptor() ([]byte, []int) { - return fileDescriptorRpc, []int{50} + return fileDescriptorRpc, []int{52} } type AuthUserGrantRoleRequest struct { @@ -1651,7 +1687,7 @@ type AuthUserGrantRoleRequest struct { func (m *AuthUserGrantRoleRequest) Reset() { *m = AuthUserGrantRoleRequest{} } func (m *AuthUserGrantRoleRequest) String() string { return proto.CompactTextString(m) } func (*AuthUserGrantRoleRequest) ProtoMessage() {} -func (*AuthUserGrantRoleRequest) Descriptor() ([]byte, []int) { return fileDescriptorRpc, []int{51} } +func (*AuthUserGrantRoleRequest) Descriptor() ([]byte, []int) { return fileDescriptorRpc, []int{53} } type AuthUserRevokeRoleRequest struct { Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"` @@ -1661,7 +1697,7 @@ type AuthUserRevokeRoleRequest struct { func (m *AuthUserRevokeRoleRequest) Reset() { *m = AuthUserRevokeRoleRequest{} } func (m *AuthUserRevokeRoleRequest) String() string { return proto.CompactTextString(m) } func (*AuthUserRevokeRoleRequest) ProtoMessage() {} -func (*AuthUserRevokeRoleRequest) Descriptor() ([]byte, []int) { return fileDescriptorRpc, []int{52} } +func (*AuthUserRevokeRoleRequest) Descriptor() ([]byte, []int) { return fileDescriptorRpc, []int{54} } type AuthRoleAddRequest struct { // name is the name of the role to add to the authentication system. @@ -1671,7 +1707,7 @@ type AuthRoleAddRequest struct { func (m *AuthRoleAddRequest) Reset() { *m = AuthRoleAddRequest{} } func (m *AuthRoleAddRequest) String() string { return proto.CompactTextString(m) } func (*AuthRoleAddRequest) ProtoMessage() {} -func (*AuthRoleAddRequest) Descriptor() ([]byte, []int) { return fileDescriptorRpc, []int{53} } +func (*AuthRoleAddRequest) Descriptor() ([]byte, []int) { return fileDescriptorRpc, []int{55} } type AuthRoleGetRequest struct { Role string `protobuf:"bytes,1,opt,name=role,proto3" json:"role,omitempty"` @@ -1680,7 +1716,7 @@ type AuthRoleGetRequest struct { func (m *AuthRoleGetRequest) Reset() { *m = AuthRoleGetRequest{} } func (m *AuthRoleGetRequest) String() string { return proto.CompactTextString(m) } func (*AuthRoleGetRequest) ProtoMessage() {} -func (*AuthRoleGetRequest) Descriptor() ([]byte, []int) { return fileDescriptorRpc, []int{54} } +func (*AuthRoleGetRequest) Descriptor() ([]byte, []int) { return fileDescriptorRpc, []int{56} } type AuthUserListRequest struct { } @@ -1688,7 +1724,7 @@ type AuthUserListRequest struct { func (m *AuthUserListRequest) Reset() { *m = AuthUserListRequest{} } func (m *AuthUserListRequest) String() string { return proto.CompactTextString(m) } func (*AuthUserListRequest) ProtoMessage() {} -func (*AuthUserListRequest) Descriptor() ([]byte, []int) { return fileDescriptorRpc, []int{55} } +func (*AuthUserListRequest) Descriptor() ([]byte, []int) { return fileDescriptorRpc, []int{57} } type AuthRoleListRequest struct { } @@ -1696,7 +1732,7 @@ type AuthRoleListRequest struct { func (m *AuthRoleListRequest) Reset() { *m = AuthRoleListRequest{} } func (m *AuthRoleListRequest) String() string { return proto.CompactTextString(m) } func (*AuthRoleListRequest) ProtoMessage() {} -func (*AuthRoleListRequest) Descriptor() ([]byte, []int) { return fileDescriptorRpc, []int{56} } +func (*AuthRoleListRequest) Descriptor() ([]byte, []int) { return fileDescriptorRpc, []int{58} } type AuthRoleDeleteRequest struct { Role string `protobuf:"bytes,1,opt,name=role,proto3" json:"role,omitempty"` @@ -1705,7 +1741,7 @@ type AuthRoleDeleteRequest struct { func (m *AuthRoleDeleteRequest) Reset() { *m = AuthRoleDeleteRequest{} } func (m *AuthRoleDeleteRequest) String() string { return proto.CompactTextString(m) } func (*AuthRoleDeleteRequest) ProtoMessage() {} -func (*AuthRoleDeleteRequest) Descriptor() ([]byte, []int) { return fileDescriptorRpc, []int{57} } +func (*AuthRoleDeleteRequest) Descriptor() ([]byte, []int) { return fileDescriptorRpc, []int{59} } type AuthRoleGrantPermissionRequest struct { // name is the name of the role which will be granted the permission. @@ -1718,7 +1754,7 @@ func (m *AuthRoleGrantPermissionRequest) Reset() { *m = AuthRoleGrantPer func (m *AuthRoleGrantPermissionRequest) String() string { return proto.CompactTextString(m) } func (*AuthRoleGrantPermissionRequest) ProtoMessage() {} func (*AuthRoleGrantPermissionRequest) Descriptor() ([]byte, []int) { - return fileDescriptorRpc, []int{58} + return fileDescriptorRpc, []int{60} } func (m *AuthRoleGrantPermissionRequest) GetPerm() *authpb.Permission { @@ -1738,7 +1774,7 @@ func (m *AuthRoleRevokePermissionRequest) Reset() { *m = AuthRoleRevokeP func (m *AuthRoleRevokePermissionRequest) String() string { return proto.CompactTextString(m) } func (*AuthRoleRevokePermissionRequest) ProtoMessage() {} func (*AuthRoleRevokePermissionRequest) Descriptor() ([]byte, []int) { - return fileDescriptorRpc, []int{59} + return fileDescriptorRpc, []int{61} } type AuthEnableResponse struct { @@ -1748,7 +1784,7 @@ type AuthEnableResponse struct { func (m *AuthEnableResponse) Reset() { *m = AuthEnableResponse{} } func (m *AuthEnableResponse) String() string { return proto.CompactTextString(m) } func (*AuthEnableResponse) ProtoMessage() {} -func (*AuthEnableResponse) Descriptor() ([]byte, []int) { return fileDescriptorRpc, []int{60} } +func (*AuthEnableResponse) Descriptor() ([]byte, []int) { return fileDescriptorRpc, []int{62} } func (m *AuthEnableResponse) GetHeader() *ResponseHeader { if m != nil { @@ -1764,7 +1800,7 @@ type AuthDisableResponse struct { func (m *AuthDisableResponse) Reset() { *m = AuthDisableResponse{} } func (m *AuthDisableResponse) String() string { return proto.CompactTextString(m) } func (*AuthDisableResponse) ProtoMessage() {} -func (*AuthDisableResponse) Descriptor() ([]byte, []int) { return fileDescriptorRpc, []int{61} } +func (*AuthDisableResponse) Descriptor() ([]byte, []int) { return fileDescriptorRpc, []int{63} } func (m *AuthDisableResponse) GetHeader() *ResponseHeader { if m != nil { @@ -1782,7 +1818,7 @@ type AuthenticateResponse struct { func (m *AuthenticateResponse) Reset() { *m = AuthenticateResponse{} } func (m *AuthenticateResponse) String() string { return proto.CompactTextString(m) } func (*AuthenticateResponse) ProtoMessage() {} -func (*AuthenticateResponse) Descriptor() ([]byte, []int) { return fileDescriptorRpc, []int{62} } +func (*AuthenticateResponse) Descriptor() ([]byte, []int) { return fileDescriptorRpc, []int{64} } func (m *AuthenticateResponse) GetHeader() *ResponseHeader { if m != nil { @@ -1798,7 +1834,7 @@ type AuthUserAddResponse struct { func (m *AuthUserAddResponse) Reset() { *m = AuthUserAddResponse{} } func (m *AuthUserAddResponse) String() string { return proto.CompactTextString(m) } func (*AuthUserAddResponse) ProtoMessage() {} -func (*AuthUserAddResponse) Descriptor() ([]byte, []int) { return fileDescriptorRpc, []int{63} } +func (*AuthUserAddResponse) Descriptor() ([]byte, []int) { return fileDescriptorRpc, []int{65} } func (m *AuthUserAddResponse) GetHeader() *ResponseHeader { if m != nil { @@ -1815,7 +1851,7 @@ type AuthUserGetResponse struct { func (m *AuthUserGetResponse) Reset() { *m = AuthUserGetResponse{} } func (m *AuthUserGetResponse) String() string { return proto.CompactTextString(m) } func (*AuthUserGetResponse) ProtoMessage() {} -func (*AuthUserGetResponse) Descriptor() ([]byte, []int) { return fileDescriptorRpc, []int{64} } +func (*AuthUserGetResponse) Descriptor() ([]byte, []int) { return fileDescriptorRpc, []int{66} } func (m *AuthUserGetResponse) GetHeader() *ResponseHeader { if m != nil { @@ -1831,7 +1867,7 @@ type AuthUserDeleteResponse struct { func (m *AuthUserDeleteResponse) Reset() { *m = AuthUserDeleteResponse{} } func (m *AuthUserDeleteResponse) String() string { return proto.CompactTextString(m) } func (*AuthUserDeleteResponse) ProtoMessage() {} -func (*AuthUserDeleteResponse) Descriptor() ([]byte, []int) { return fileDescriptorRpc, []int{65} } +func (*AuthUserDeleteResponse) Descriptor() ([]byte, []int) { return fileDescriptorRpc, []int{67} } func (m *AuthUserDeleteResponse) GetHeader() *ResponseHeader { if m != nil { @@ -1848,7 +1884,7 @@ func (m *AuthUserChangePasswordResponse) Reset() { *m = AuthUserChangePa func (m *AuthUserChangePasswordResponse) String() string { return proto.CompactTextString(m) } func (*AuthUserChangePasswordResponse) ProtoMessage() {} func (*AuthUserChangePasswordResponse) Descriptor() ([]byte, []int) { - return fileDescriptorRpc, []int{66} + return fileDescriptorRpc, []int{68} } func (m *AuthUserChangePasswordResponse) GetHeader() *ResponseHeader { @@ -1865,7 +1901,7 @@ type AuthUserGrantRoleResponse struct { func (m *AuthUserGrantRoleResponse) Reset() { *m = AuthUserGrantRoleResponse{} } func (m *AuthUserGrantRoleResponse) String() string { return proto.CompactTextString(m) } func (*AuthUserGrantRoleResponse) ProtoMessage() {} -func (*AuthUserGrantRoleResponse) Descriptor() ([]byte, []int) { return fileDescriptorRpc, []int{67} } +func (*AuthUserGrantRoleResponse) Descriptor() ([]byte, []int) { return fileDescriptorRpc, []int{69} } func (m *AuthUserGrantRoleResponse) GetHeader() *ResponseHeader { if m != nil { @@ -1881,7 +1917,7 @@ type AuthUserRevokeRoleResponse struct { func (m *AuthUserRevokeRoleResponse) Reset() { *m = AuthUserRevokeRoleResponse{} } func (m *AuthUserRevokeRoleResponse) String() string { return proto.CompactTextString(m) } func (*AuthUserRevokeRoleResponse) ProtoMessage() {} -func (*AuthUserRevokeRoleResponse) Descriptor() ([]byte, []int) { return fileDescriptorRpc, []int{68} } +func (*AuthUserRevokeRoleResponse) Descriptor() ([]byte, []int) { return fileDescriptorRpc, []int{70} } func (m *AuthUserRevokeRoleResponse) GetHeader() *ResponseHeader { if m != nil { @@ -1897,7 +1933,7 @@ type AuthRoleAddResponse struct { func (m *AuthRoleAddResponse) Reset() { *m = AuthRoleAddResponse{} } func (m *AuthRoleAddResponse) String() string { return proto.CompactTextString(m) } func (*AuthRoleAddResponse) ProtoMessage() {} -func (*AuthRoleAddResponse) Descriptor() ([]byte, []int) { return fileDescriptorRpc, []int{69} } +func (*AuthRoleAddResponse) Descriptor() ([]byte, []int) { return fileDescriptorRpc, []int{71} } func (m *AuthRoleAddResponse) GetHeader() *ResponseHeader { if m != nil { @@ -1914,7 +1950,7 @@ type AuthRoleGetResponse struct { func (m *AuthRoleGetResponse) Reset() { *m = AuthRoleGetResponse{} } func (m *AuthRoleGetResponse) String() string { return proto.CompactTextString(m) } func (*AuthRoleGetResponse) ProtoMessage() {} -func (*AuthRoleGetResponse) Descriptor() ([]byte, []int) { return fileDescriptorRpc, []int{70} } +func (*AuthRoleGetResponse) Descriptor() ([]byte, []int) { return fileDescriptorRpc, []int{72} } func (m *AuthRoleGetResponse) GetHeader() *ResponseHeader { if m != nil { @@ -1938,7 +1974,7 @@ type AuthRoleListResponse struct { func (m *AuthRoleListResponse) Reset() { *m = AuthRoleListResponse{} } func (m *AuthRoleListResponse) String() string { return proto.CompactTextString(m) } func (*AuthRoleListResponse) ProtoMessage() {} -func (*AuthRoleListResponse) Descriptor() ([]byte, []int) { return fileDescriptorRpc, []int{71} } +func (*AuthRoleListResponse) Descriptor() ([]byte, []int) { return fileDescriptorRpc, []int{73} } func (m *AuthRoleListResponse) GetHeader() *ResponseHeader { if m != nil { @@ -1955,7 +1991,7 @@ type AuthUserListResponse struct { func (m *AuthUserListResponse) Reset() { *m = AuthUserListResponse{} } func (m *AuthUserListResponse) String() string { return proto.CompactTextString(m) } func (*AuthUserListResponse) ProtoMessage() {} -func (*AuthUserListResponse) Descriptor() ([]byte, []int) { return fileDescriptorRpc, []int{72} } +func (*AuthUserListResponse) Descriptor() ([]byte, []int) { return fileDescriptorRpc, []int{74} } func (m *AuthUserListResponse) GetHeader() *ResponseHeader { if m != nil { @@ -1971,7 +2007,7 @@ type AuthRoleDeleteResponse struct { func (m *AuthRoleDeleteResponse) Reset() { *m = AuthRoleDeleteResponse{} } func (m *AuthRoleDeleteResponse) String() string { return proto.CompactTextString(m) } func (*AuthRoleDeleteResponse) ProtoMessage() {} -func (*AuthRoleDeleteResponse) Descriptor() ([]byte, []int) { return fileDescriptorRpc, []int{73} } +func (*AuthRoleDeleteResponse) Descriptor() ([]byte, []int) { return fileDescriptorRpc, []int{75} } func (m *AuthRoleDeleteResponse) GetHeader() *ResponseHeader { if m != nil { @@ -1988,7 +2024,7 @@ func (m *AuthRoleGrantPermissionResponse) Reset() { *m = AuthRoleGrantPe func (m *AuthRoleGrantPermissionResponse) String() string { return proto.CompactTextString(m) } func (*AuthRoleGrantPermissionResponse) ProtoMessage() {} func (*AuthRoleGrantPermissionResponse) Descriptor() ([]byte, []int) { - return fileDescriptorRpc, []int{74} + return fileDescriptorRpc, []int{76} } func (m *AuthRoleGrantPermissionResponse) GetHeader() *ResponseHeader { @@ -2006,7 +2042,7 @@ func (m *AuthRoleRevokePermissionResponse) Reset() { *m = AuthRoleRevoke func (m *AuthRoleRevokePermissionResponse) String() string { return proto.CompactTextString(m) } func (*AuthRoleRevokePermissionResponse) ProtoMessage() {} func (*AuthRoleRevokePermissionResponse) Descriptor() ([]byte, []int) { - return fileDescriptorRpc, []int{75} + return fileDescriptorRpc, []int{77} } func (m *AuthRoleRevokePermissionResponse) GetHeader() *ResponseHeader { @@ -2045,6 +2081,8 @@ func init() { proto.RegisterType((*LeaseRevokeResponse)(nil), "etcdserverpb.LeaseRevokeResponse") proto.RegisterType((*LeaseKeepAliveRequest)(nil), "etcdserverpb.LeaseKeepAliveRequest") proto.RegisterType((*LeaseKeepAliveResponse)(nil), "etcdserverpb.LeaseKeepAliveResponse") + proto.RegisterType((*LeaseTimeToLiveRequest)(nil), "etcdserverpb.LeaseTimeToLiveRequest") + proto.RegisterType((*LeaseTimeToLiveResponse)(nil), "etcdserverpb.LeaseTimeToLiveResponse") proto.RegisterType((*Member)(nil), "etcdserverpb.Member") proto.RegisterType((*MemberAddRequest)(nil), "etcdserverpb.MemberAddRequest") proto.RegisterType((*MemberAddResponse)(nil), "etcdserverpb.MemberAddResponse") @@ -2452,6 +2490,8 @@ type LeaseClient interface { // LeaseKeepAlive keeps the lease alive by streaming keep alive requests from the client // to the server and streaming keep alive responses from the server to the client. LeaseKeepAlive(ctx context.Context, opts ...grpc.CallOption) (Lease_LeaseKeepAliveClient, error) + // LeaseTimeToLive retrieves lease information. + LeaseTimeToLive(ctx context.Context, in *LeaseTimeToLiveRequest, opts ...grpc.CallOption) (*LeaseTimeToLiveResponse, error) } type leaseClient struct { @@ -2511,6 +2551,15 @@ func (x *leaseLeaseKeepAliveClient) Recv() (*LeaseKeepAliveResponse, error) { return m, nil } +func (c *leaseClient) LeaseTimeToLive(ctx context.Context, in *LeaseTimeToLiveRequest, opts ...grpc.CallOption) (*LeaseTimeToLiveResponse, error) { + out := new(LeaseTimeToLiveResponse) + err := grpc.Invoke(ctx, "/etcdserverpb.Lease/LeaseTimeToLive", in, out, c.cc, opts...) + if err != nil { + return nil, err + } + return out, nil +} + // Server API for Lease service type LeaseServer interface { @@ -2523,6 +2572,8 @@ type LeaseServer interface { // LeaseKeepAlive keeps the lease alive by streaming keep alive requests from the client // to the server and streaming keep alive responses from the server to the client. LeaseKeepAlive(Lease_LeaseKeepAliveServer) error + // LeaseTimeToLive retrieves lease information. + LeaseTimeToLive(context.Context, *LeaseTimeToLiveRequest) (*LeaseTimeToLiveResponse, error) } func RegisterLeaseServer(s *grpc.Server, srv LeaseServer) { @@ -2591,6 +2642,24 @@ func (x *leaseLeaseKeepAliveServer) Recv() (*LeaseKeepAliveRequest, error) { return m, nil } +func _Lease_LeaseTimeToLive_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(LeaseTimeToLiveRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(LeaseServer).LeaseTimeToLive(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/etcdserverpb.Lease/LeaseTimeToLive", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(LeaseServer).LeaseTimeToLive(ctx, req.(*LeaseTimeToLiveRequest)) + } + return interceptor(ctx, in, info, handler) +} + var _Lease_serviceDesc = grpc.ServiceDesc{ ServiceName: "etcdserverpb.Lease", HandlerType: (*LeaseServer)(nil), @@ -2603,6 +2672,10 @@ var _Lease_serviceDesc = grpc.ServiceDesc{ MethodName: "LeaseRevoke", Handler: _Lease_LeaseRevoke_Handler, }, + { + MethodName: "LeaseTimeToLive", + Handler: _Lease_LeaseTimeToLive_Handler, + }, }, Streams: []grpc.StreamDesc{ { @@ -4827,6 +4900,90 @@ func (m *LeaseKeepAliveResponse) MarshalTo(data []byte) (int, error) { return i, nil } +func (m *LeaseTimeToLiveRequest) Marshal() (data []byte, err error) { + size := m.Size() + data = make([]byte, size) + n, err := m.MarshalTo(data) + if err != nil { + return nil, err + } + return data[:n], nil +} + +func (m *LeaseTimeToLiveRequest) MarshalTo(data []byte) (int, error) { + var i int + _ = i + var l int + _ = l + if m.ID != 0 { + data[i] = 0x8 + i++ + i = encodeVarintRpc(data, i, uint64(m.ID)) + } + if m.Keys { + data[i] = 0x10 + i++ + if m.Keys { + data[i] = 1 + } else { + data[i] = 0 + } + i++ + } + return i, nil +} + +func (m *LeaseTimeToLiveResponse) Marshal() (data []byte, err error) { + size := m.Size() + data = make([]byte, size) + n, err := m.MarshalTo(data) + if err != nil { + return nil, err + } + return data[:n], nil +} + +func (m *LeaseTimeToLiveResponse) MarshalTo(data []byte) (int, error) { + var i int + _ = i + var l int + _ = l + if m.Header != nil { + data[i] = 0xa + i++ + i = encodeVarintRpc(data, i, uint64(m.Header.Size())) + n25, err := m.Header.MarshalTo(data[i:]) + if err != nil { + return 0, err + } + i += n25 + } + if m.ID != 0 { + data[i] = 0x10 + i++ + i = encodeVarintRpc(data, i, uint64(m.ID)) + } + if m.TTL != 0 { + data[i] = 0x18 + i++ + i = encodeVarintRpc(data, i, uint64(m.TTL)) + } + if m.GrantedTTL != 0 { + data[i] = 0x20 + i++ + i = encodeVarintRpc(data, i, uint64(m.GrantedTTL)) + } + if len(m.Keys) > 0 { + for _, b := range m.Keys { + data[i] = 0x2a + i++ + i = encodeVarintRpc(data, i, uint64(len(b))) + i += copy(data[i:], b) + } + } + return i, nil +} + func (m *Member) Marshal() (data []byte, err error) { size := m.Size() data = make([]byte, size) @@ -4938,21 +5095,21 @@ func (m *MemberAddResponse) MarshalTo(data []byte) (int, error) { data[i] = 0xa i++ i = encodeVarintRpc(data, i, uint64(m.Header.Size())) - n25, err := m.Header.MarshalTo(data[i:]) + n26, err := m.Header.MarshalTo(data[i:]) if err != nil { return 0, err } - i += n25 + i += n26 } if m.Member != nil { data[i] = 0x12 i++ i = encodeVarintRpc(data, i, uint64(m.Member.Size())) - n26, err := m.Member.MarshalTo(data[i:]) + n27, err := m.Member.MarshalTo(data[i:]) if err != nil { return 0, err } - i += n26 + i += n27 } return i, nil } @@ -4999,11 +5156,11 @@ func (m *MemberRemoveResponse) MarshalTo(data []byte) (int, error) { data[i] = 0xa i++ i = encodeVarintRpc(data, i, uint64(m.Header.Size())) - n27, err := m.Header.MarshalTo(data[i:]) + n28, err := m.Header.MarshalTo(data[i:]) if err != nil { return 0, err } - i += n27 + i += n28 } return i, nil } @@ -5065,11 +5222,11 @@ func (m *MemberUpdateResponse) MarshalTo(data []byte) (int, error) { data[i] = 0xa i++ i = encodeVarintRpc(data, i, uint64(m.Header.Size())) - n28, err := m.Header.MarshalTo(data[i:]) + n29, err := m.Header.MarshalTo(data[i:]) if err != nil { return 0, err } - i += n28 + i += n29 } return i, nil } @@ -5111,11 +5268,11 @@ func (m *MemberListResponse) MarshalTo(data []byte) (int, error) { data[i] = 0xa i++ i = encodeVarintRpc(data, i, uint64(m.Header.Size())) - n29, err := m.Header.MarshalTo(data[i:]) + n30, err := m.Header.MarshalTo(data[i:]) if err != nil { return 0, err } - i += n29 + i += n30 } if len(m.Members) > 0 { for _, msg := range m.Members { @@ -5169,11 +5326,11 @@ func (m *DefragmentResponse) MarshalTo(data []byte) (int, error) { data[i] = 0xa i++ i = encodeVarintRpc(data, i, uint64(m.Header.Size())) - n30, err := m.Header.MarshalTo(data[i:]) + n31, err := m.Header.MarshalTo(data[i:]) if err != nil { return 0, err } - i += n30 + i += n31 } return i, nil } @@ -5258,11 +5415,11 @@ func (m *AlarmResponse) MarshalTo(data []byte) (int, error) { data[i] = 0xa i++ i = encodeVarintRpc(data, i, uint64(m.Header.Size())) - n31, err := m.Header.MarshalTo(data[i:]) + n32, err := m.Header.MarshalTo(data[i:]) if err != nil { return 0, err } - i += n31 + i += n32 } if len(m.Alarms) > 0 { for _, msg := range m.Alarms { @@ -5316,11 +5473,11 @@ func (m *StatusResponse) MarshalTo(data []byte) (int, error) { data[i] = 0xa i++ i = encodeVarintRpc(data, i, uint64(m.Header.Size())) - n32, err := m.Header.MarshalTo(data[i:]) + n33, err := m.Header.MarshalTo(data[i:]) if err != nil { return 0, err } - i += n32 + i += n33 } if len(m.Version) > 0 { data[i] = 0x12 @@ -5718,11 +5875,11 @@ func (m *AuthRoleGrantPermissionRequest) MarshalTo(data []byte) (int, error) { data[i] = 0x12 i++ i = encodeVarintRpc(data, i, uint64(m.Perm.Size())) - n33, err := m.Perm.MarshalTo(data[i:]) + n34, err := m.Perm.MarshalTo(data[i:]) if err != nil { return 0, err } - i += n33 + i += n34 } return i, nil } @@ -5782,11 +5939,11 @@ func (m *AuthEnableResponse) MarshalTo(data []byte) (int, error) { data[i] = 0xa i++ i = encodeVarintRpc(data, i, uint64(m.Header.Size())) - n34, err := m.Header.MarshalTo(data[i:]) + n35, err := m.Header.MarshalTo(data[i:]) if err != nil { return 0, err } - i += n34 + i += n35 } return i, nil } @@ -5810,11 +5967,11 @@ func (m *AuthDisableResponse) MarshalTo(data []byte) (int, error) { data[i] = 0xa i++ i = encodeVarintRpc(data, i, uint64(m.Header.Size())) - n35, err := m.Header.MarshalTo(data[i:]) + n36, err := m.Header.MarshalTo(data[i:]) if err != nil { return 0, err } - i += n35 + i += n36 } return i, nil } @@ -5838,11 +5995,11 @@ func (m *AuthenticateResponse) MarshalTo(data []byte) (int, error) { data[i] = 0xa i++ i = encodeVarintRpc(data, i, uint64(m.Header.Size())) - n36, err := m.Header.MarshalTo(data[i:]) + n37, err := m.Header.MarshalTo(data[i:]) if err != nil { return 0, err } - i += n36 + i += n37 } if len(m.Token) > 0 { data[i] = 0x12 @@ -5872,11 +6029,11 @@ func (m *AuthUserAddResponse) MarshalTo(data []byte) (int, error) { data[i] = 0xa i++ i = encodeVarintRpc(data, i, uint64(m.Header.Size())) - n37, err := m.Header.MarshalTo(data[i:]) + n38, err := m.Header.MarshalTo(data[i:]) if err != nil { return 0, err } - i += n37 + i += n38 } return i, nil } @@ -5900,11 +6057,11 @@ func (m *AuthUserGetResponse) MarshalTo(data []byte) (int, error) { data[i] = 0xa i++ i = encodeVarintRpc(data, i, uint64(m.Header.Size())) - n38, err := m.Header.MarshalTo(data[i:]) + n39, err := m.Header.MarshalTo(data[i:]) if err != nil { return 0, err } - i += n38 + i += n39 } if len(m.Roles) > 0 { for _, s := range m.Roles { @@ -5943,11 +6100,11 @@ func (m *AuthUserDeleteResponse) MarshalTo(data []byte) (int, error) { data[i] = 0xa i++ i = encodeVarintRpc(data, i, uint64(m.Header.Size())) - n39, err := m.Header.MarshalTo(data[i:]) + n40, err := m.Header.MarshalTo(data[i:]) if err != nil { return 0, err } - i += n39 + i += n40 } return i, nil } @@ -5971,11 +6128,11 @@ func (m *AuthUserChangePasswordResponse) MarshalTo(data []byte) (int, error) { data[i] = 0xa i++ i = encodeVarintRpc(data, i, uint64(m.Header.Size())) - n40, err := m.Header.MarshalTo(data[i:]) + n41, err := m.Header.MarshalTo(data[i:]) if err != nil { return 0, err } - i += n40 + i += n41 } return i, nil } @@ -5999,11 +6156,11 @@ func (m *AuthUserGrantRoleResponse) MarshalTo(data []byte) (int, error) { data[i] = 0xa i++ i = encodeVarintRpc(data, i, uint64(m.Header.Size())) - n41, err := m.Header.MarshalTo(data[i:]) + n42, err := m.Header.MarshalTo(data[i:]) if err != nil { return 0, err } - i += n41 + i += n42 } return i, nil } @@ -6027,11 +6184,11 @@ func (m *AuthUserRevokeRoleResponse) MarshalTo(data []byte) (int, error) { data[i] = 0xa i++ i = encodeVarintRpc(data, i, uint64(m.Header.Size())) - n42, err := m.Header.MarshalTo(data[i:]) + n43, err := m.Header.MarshalTo(data[i:]) if err != nil { return 0, err } - i += n42 + i += n43 } return i, nil } @@ -6055,11 +6212,11 @@ func (m *AuthRoleAddResponse) MarshalTo(data []byte) (int, error) { data[i] = 0xa i++ i = encodeVarintRpc(data, i, uint64(m.Header.Size())) - n43, err := m.Header.MarshalTo(data[i:]) + n44, err := m.Header.MarshalTo(data[i:]) if err != nil { return 0, err } - i += n43 + i += n44 } return i, nil } @@ -6083,11 +6240,11 @@ func (m *AuthRoleGetResponse) MarshalTo(data []byte) (int, error) { data[i] = 0xa i++ i = encodeVarintRpc(data, i, uint64(m.Header.Size())) - n44, err := m.Header.MarshalTo(data[i:]) + n45, err := m.Header.MarshalTo(data[i:]) if err != nil { return 0, err } - i += n44 + i += n45 } if len(m.Perm) > 0 { for _, msg := range m.Perm { @@ -6123,11 +6280,11 @@ func (m *AuthRoleListResponse) MarshalTo(data []byte) (int, error) { data[i] = 0xa i++ i = encodeVarintRpc(data, i, uint64(m.Header.Size())) - n45, err := m.Header.MarshalTo(data[i:]) + n46, err := m.Header.MarshalTo(data[i:]) if err != nil { return 0, err } - i += n45 + i += n46 } if len(m.Roles) > 0 { for _, s := range m.Roles { @@ -6166,11 +6323,11 @@ func (m *AuthUserListResponse) MarshalTo(data []byte) (int, error) { data[i] = 0xa i++ i = encodeVarintRpc(data, i, uint64(m.Header.Size())) - n46, err := m.Header.MarshalTo(data[i:]) + n47, err := m.Header.MarshalTo(data[i:]) if err != nil { return 0, err } - i += n46 + i += n47 } if len(m.Users) > 0 { for _, s := range m.Users { @@ -6209,11 +6366,11 @@ func (m *AuthRoleDeleteResponse) MarshalTo(data []byte) (int, error) { data[i] = 0xa i++ i = encodeVarintRpc(data, i, uint64(m.Header.Size())) - n47, err := m.Header.MarshalTo(data[i:]) + n48, err := m.Header.MarshalTo(data[i:]) if err != nil { return 0, err } - i += n47 + i += n48 } return i, nil } @@ -6237,11 +6394,11 @@ func (m *AuthRoleGrantPermissionResponse) MarshalTo(data []byte) (int, error) { data[i] = 0xa i++ i = encodeVarintRpc(data, i, uint64(m.Header.Size())) - n48, err := m.Header.MarshalTo(data[i:]) + n49, err := m.Header.MarshalTo(data[i:]) if err != nil { return 0, err } - i += n48 + i += n49 } return i, nil } @@ -6265,11 +6422,11 @@ func (m *AuthRoleRevokePermissionResponse) MarshalTo(data []byte) (int, error) { data[i] = 0xa i++ i = encodeVarintRpc(data, i, uint64(m.Header.Size())) - n49, err := m.Header.MarshalTo(data[i:]) + n50, err := m.Header.MarshalTo(data[i:]) if err != nil { return 0, err } - i += n49 + i += n50 } return i, nil } @@ -6839,6 +6996,43 @@ func (m *LeaseKeepAliveResponse) Size() (n int) { return n } +func (m *LeaseTimeToLiveRequest) Size() (n int) { + var l int + _ = l + if m.ID != 0 { + n += 1 + sovRpc(uint64(m.ID)) + } + if m.Keys { + n += 2 + } + return n +} + +func (m *LeaseTimeToLiveResponse) Size() (n int) { + var l int + _ = l + if m.Header != nil { + l = m.Header.Size() + n += 1 + l + sovRpc(uint64(l)) + } + if m.ID != 0 { + n += 1 + sovRpc(uint64(m.ID)) + } + if m.TTL != 0 { + n += 1 + sovRpc(uint64(m.TTL)) + } + if m.GrantedTTL != 0 { + n += 1 + sovRpc(uint64(m.GrantedTTL)) + } + if len(m.Keys) > 0 { + for _, b := range m.Keys { + l = len(b) + n += 1 + l + sovRpc(uint64(l)) + } + } + return n +} + func (m *Member) Size() (n int) { var l int _ = l @@ -10914,6 +11108,264 @@ func (m *LeaseKeepAliveResponse) Unmarshal(data []byte) error { } return nil } +func (m *LeaseTimeToLiveRequest) Unmarshal(data []byte) error { + l := len(data) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowRpc + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := data[iNdEx] + iNdEx++ + wire |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: LeaseTimeToLiveRequest: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: LeaseTimeToLiveRequest: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field ID", wireType) + } + m.ID = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowRpc + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := data[iNdEx] + iNdEx++ + m.ID |= (int64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + case 2: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field Keys", wireType) + } + var v int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowRpc + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := data[iNdEx] + iNdEx++ + v |= (int(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + m.Keys = bool(v != 0) + default: + iNdEx = preIndex + skippy, err := skipRpc(data[iNdEx:]) + if err != nil { + return err + } + if skippy < 0 { + return ErrInvalidLengthRpc + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *LeaseTimeToLiveResponse) Unmarshal(data []byte) error { + l := len(data) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowRpc + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := data[iNdEx] + iNdEx++ + wire |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: LeaseTimeToLiveResponse: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: LeaseTimeToLiveResponse: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Header", 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 + } + if m.Header == nil { + m.Header = &ResponseHeader{} + } + if err := m.Header.Unmarshal(data[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 2: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field ID", wireType) + } + m.ID = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowRpc + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := data[iNdEx] + iNdEx++ + m.ID |= (int64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + case 3: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field TTL", wireType) + } + m.TTL = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowRpc + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := data[iNdEx] + iNdEx++ + m.TTL |= (int64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + case 4: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field GrantedTTL", wireType) + } + m.GrantedTTL = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowRpc + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := data[iNdEx] + iNdEx++ + m.GrantedTTL |= (int64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + case 5: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Keys", wireType) + } + var byteLen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowRpc + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := data[iNdEx] + iNdEx++ + byteLen |= (int(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + if byteLen < 0 { + return ErrInvalidLengthRpc + } + postIndex := iNdEx + byteLen + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Keys = append(m.Keys, make([]byte, postIndex-iNdEx)) + copy(m.Keys[len(m.Keys)-1], data[iNdEx:postIndex]) + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipRpc(data[iNdEx:]) + if err != nil { + return err + } + if skippy < 0 { + return ErrInvalidLengthRpc + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} func (m *Member) Unmarshal(data []byte) error { l := len(data) iNdEx := 0 @@ -15407,209 +15859,214 @@ var ( ) var fileDescriptorRpc = []byte{ - // 3256 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0xb4, 0x5a, 0x4f, 0x73, 0x1b, 0xc7, - 0xb1, 0xe7, 0x02, 0x20, 0x40, 0x34, 0x40, 0x10, 0x1a, 0x52, 0x32, 0xb8, 0x92, 0x28, 0x6a, 0xf4, - 0x8f, 0x92, 0x6c, 0xc2, 0xa6, 0xfd, 0xde, 0x41, 0xef, 0x95, 0xab, 0x28, 0x02, 0x16, 0x19, 0xd2, - 0xa4, 0xbc, 0xa4, 0x64, 0xa7, 0xca, 0x15, 0xd6, 0x12, 0x18, 0x01, 0x28, 0x02, 0xbb, 0xf0, 0xee, - 0x02, 0x12, 0x9d, 0xa4, 0x2a, 0xe5, 0x8a, 0x0f, 0xc9, 0x31, 0x3e, 0x24, 0x71, 0x8e, 0xf9, 0x0c, - 0xb9, 0xe5, 0x03, 0xa4, 0x72, 0x89, 0xab, 0xf2, 0x05, 0x52, 0x4e, 0x0e, 0x39, 0xe4, 0x9e, 0xca, - 0x21, 0x95, 0xd4, 0xfc, 0xdb, 0x9d, 0x5d, 0xec, 0x82, 0x74, 0x36, 0xbe, 0x48, 0x98, 0x9e, 0x9e, - 0xfe, 0x75, 0xf7, 0x4c, 0xf7, 0xf4, 0xf4, 0x12, 0x8a, 0xce, 0xb0, 0xb5, 0x3e, 0x74, 0x6c, 0xcf, - 0x46, 0x65, 0xe2, 0xb5, 0xda, 0x2e, 0x71, 0xc6, 0xc4, 0x19, 0x9e, 0xe8, 0x4b, 0x1d, 0xbb, 0x63, - 0xb3, 0x89, 0x3a, 0xfd, 0xc5, 0x79, 0xf4, 0x65, 0xca, 0x53, 0x1f, 0x8c, 0x5b, 0x2d, 0xf6, 0xcf, - 0xf0, 0xa4, 0x7e, 0x3a, 0x16, 0x53, 0x57, 0xd9, 0x94, 0x39, 0xf2, 0xba, 0xec, 0x9f, 0xe1, 0x09, - 0xfb, 0x4f, 0x4c, 0x5e, 0xeb, 0xd8, 0x76, 0xa7, 0x4f, 0xea, 0xe6, 0xb0, 0x57, 0x37, 0x2d, 0xcb, - 0xf6, 0x4c, 0xaf, 0x67, 0x5b, 0x2e, 0x9f, 0xc5, 0x9f, 0x6b, 0x50, 0x31, 0x88, 0x3b, 0xb4, 0x2d, - 0x97, 0x6c, 0x13, 0xb3, 0x4d, 0x1c, 0x74, 0x1d, 0xa0, 0xd5, 0x1f, 0xb9, 0x1e, 0x71, 0x8e, 0x7b, - 0xed, 0x9a, 0xb6, 0xaa, 0xad, 0xe5, 0x8c, 0xa2, 0xa0, 0xec, 0xb4, 0xd1, 0x55, 0x28, 0x0e, 0xc8, - 0xe0, 0x84, 0xcf, 0x66, 0xd8, 0xec, 0x1c, 0x27, 0xec, 0xb4, 0x91, 0x0e, 0x73, 0x0e, 0x19, 0xf7, - 0xdc, 0x9e, 0x6d, 0xd5, 0xb2, 0xab, 0xda, 0x5a, 0xd6, 0xf0, 0xc7, 0x74, 0xa1, 0x63, 0xbe, 0xf0, - 0x8e, 0x3d, 0xe2, 0x0c, 0x6a, 0x39, 0xbe, 0x90, 0x12, 0x8e, 0x88, 0x33, 0xc0, 0x5f, 0x65, 0xa1, - 0x6c, 0x98, 0x56, 0x87, 0x18, 0xe4, 0x93, 0x11, 0x71, 0x3d, 0x54, 0x85, 0xec, 0x29, 0x39, 0x63, - 0xf0, 0x65, 0x83, 0xfe, 0xe4, 0xeb, 0xad, 0x0e, 0x39, 0x26, 0x16, 0x07, 0x2e, 0xd3, 0xf5, 0x56, - 0x87, 0x34, 0xad, 0x36, 0x5a, 0x82, 0xd9, 0x7e, 0x6f, 0xd0, 0xf3, 0x04, 0x2a, 0x1f, 0x84, 0xd4, - 0xc9, 0x45, 0xd4, 0xd9, 0x02, 0x70, 0x6d, 0xc7, 0x3b, 0xb6, 0x9d, 0x36, 0x71, 0x6a, 0xb3, 0xab, - 0xda, 0x5a, 0x65, 0xe3, 0xf6, 0xba, 0xba, 0x11, 0xeb, 0xaa, 0x42, 0xeb, 0x87, 0xb6, 0xe3, 0x1d, - 0x50, 0x5e, 0xa3, 0xe8, 0xca, 0x9f, 0xe8, 0x3d, 0x28, 0x31, 0x21, 0x9e, 0xe9, 0x74, 0x88, 0x57, - 0xcb, 0x33, 0x29, 0x77, 0xce, 0x91, 0x72, 0xc4, 0x98, 0x0d, 0x06, 0xcf, 0x7f, 0x23, 0x0c, 0x65, - 0x97, 0x38, 0x3d, 0xb3, 0xdf, 0xfb, 0xd4, 0x3c, 0xe9, 0x93, 0x5a, 0x61, 0x55, 0x5b, 0x9b, 0x33, - 0x42, 0x34, 0x6a, 0xff, 0x29, 0x39, 0x73, 0x8f, 0x6d, 0xab, 0x7f, 0x56, 0x9b, 0x63, 0x0c, 0x73, - 0x94, 0x70, 0x60, 0xf5, 0xcf, 0xd8, 0xa6, 0xd9, 0x23, 0xcb, 0xe3, 0xb3, 0x45, 0x36, 0x5b, 0x64, - 0x14, 0x3a, 0x8d, 0xd7, 0xa1, 0xe8, 0xeb, 0x8f, 0xe6, 0x20, 0xb7, 0x7f, 0xb0, 0xdf, 0xac, 0xce, - 0x20, 0x80, 0xfc, 0xe6, 0xe1, 0x56, 0x73, 0xbf, 0x51, 0xd5, 0x50, 0x09, 0x0a, 0x8d, 0x26, 0x1f, - 0x64, 0xf0, 0x63, 0x80, 0x40, 0x53, 0x54, 0x80, 0xec, 0x6e, 0xf3, 0xbb, 0xd5, 0x19, 0xca, 0xf3, - 0xbc, 0x69, 0x1c, 0xee, 0x1c, 0xec, 0x57, 0x35, 0xba, 0x78, 0xcb, 0x68, 0x6e, 0x1e, 0x35, 0xab, - 0x19, 0xca, 0xf1, 0xfe, 0x41, 0xa3, 0x9a, 0x45, 0x45, 0x98, 0x7d, 0xbe, 0xb9, 0xf7, 0xac, 0x59, - 0xcd, 0xe1, 0x2f, 0x34, 0x98, 0x17, 0xb6, 0xf3, 0xf3, 0x85, 0xde, 0x81, 0x7c, 0x97, 0x9d, 0x31, - 0xb6, 0xad, 0xa5, 0x8d, 0x6b, 0x11, 0x47, 0x85, 0xce, 0xa1, 0x21, 0x78, 0x11, 0x86, 0xec, 0xe9, - 0xd8, 0xad, 0x65, 0x56, 0xb3, 0x6b, 0xa5, 0x8d, 0xea, 0x3a, 0x3f, 0xfc, 0xeb, 0xbb, 0xe4, 0xec, - 0xb9, 0xd9, 0x1f, 0x11, 0x83, 0x4e, 0x22, 0x04, 0xb9, 0x81, 0xed, 0x10, 0xb6, 0xfb, 0x73, 0x06, - 0xfb, 0x4d, 0x8f, 0x04, 0x73, 0x80, 0xd8, 0x79, 0x3e, 0xc0, 0x2d, 0x80, 0xa7, 0x23, 0x2f, 0xf9, - 0x94, 0x2d, 0xc1, 0xec, 0x98, 0xca, 0x15, 0x27, 0x8c, 0x0f, 0xd8, 0xf1, 0x22, 0xa6, 0x4b, 0xfc, - 0xe3, 0x45, 0x07, 0xe8, 0x35, 0x28, 0x0c, 0x1d, 0x32, 0x3e, 0x3e, 0x1d, 0x33, 0x8c, 0x39, 0x23, - 0x4f, 0x87, 0xbb, 0x63, 0x6c, 0x41, 0x89, 0x81, 0xa4, 0xb2, 0xfb, 0x7e, 0x20, 0x3d, 0xc3, 0x96, - 0x4d, 0xda, 0x2e, 0xf1, 0x3e, 0x06, 0xd4, 0x20, 0x7d, 0xe2, 0x91, 0x34, 0x21, 0xa4, 0x58, 0x93, - 0x0d, 0x59, 0xf3, 0x33, 0x0d, 0x16, 0x43, 0xe2, 0x53, 0x99, 0x55, 0x83, 0x42, 0x9b, 0x09, 0xe3, - 0x1a, 0x64, 0x0d, 0x39, 0x44, 0x0f, 0x61, 0x4e, 0x28, 0xe0, 0xd6, 0xb2, 0x09, 0xbb, 0x5d, 0xe0, - 0x3a, 0xb9, 0xf8, 0x6f, 0x1a, 0x14, 0x85, 0xa1, 0x07, 0x43, 0xb4, 0x09, 0xf3, 0x0e, 0x1f, 0x1c, - 0x33, 0x7b, 0x84, 0x46, 0x7a, 0x72, 0x24, 0x6e, 0xcf, 0x18, 0x65, 0xb1, 0x84, 0x91, 0xd1, 0xff, - 0x41, 0x49, 0x8a, 0x18, 0x8e, 0x3c, 0xe1, 0xf2, 0x5a, 0x58, 0x40, 0x70, 0x72, 0xb6, 0x67, 0x0c, - 0x10, 0xec, 0x4f, 0x47, 0x1e, 0x3a, 0x82, 0x25, 0xb9, 0x98, 0x5b, 0x23, 0xd4, 0xc8, 0x32, 0x29, - 0xab, 0x61, 0x29, 0x93, 0x5b, 0xb5, 0x3d, 0x63, 0x20, 0xb1, 0x5e, 0x99, 0x7c, 0x5c, 0x84, 0x82, - 0xa0, 0xe2, 0xbf, 0x6b, 0x00, 0xd2, 0xa1, 0x07, 0x43, 0xd4, 0x80, 0x8a, 0x23, 0x46, 0x21, 0x83, - 0xaf, 0xc6, 0x1a, 0x2c, 0xf6, 0x61, 0xc6, 0x98, 0x97, 0x8b, 0xb8, 0xc9, 0xef, 0x42, 0xd9, 0x97, - 0x12, 0xd8, 0xbc, 0x1c, 0x63, 0xb3, 0x2f, 0xa1, 0x24, 0x17, 0x50, 0xab, 0x3f, 0x84, 0xcb, 0xfe, - 0xfa, 0x18, 0xb3, 0x6f, 0x4e, 0x31, 0xdb, 0x17, 0xb8, 0x28, 0x25, 0xa8, 0x86, 0x03, 0xcd, 0xdb, - 0x9c, 0x8c, 0xbf, 0xcc, 0x42, 0x61, 0xcb, 0x1e, 0x0c, 0x4d, 0x87, 0xee, 0x51, 0xde, 0x21, 0xee, - 0xa8, 0xef, 0x31, 0x73, 0x2b, 0x1b, 0xb7, 0xc2, 0x08, 0x82, 0x4d, 0xfe, 0x6f, 0x30, 0x56, 0x43, - 0x2c, 0xa1, 0x8b, 0x45, 0x9a, 0xce, 0x5c, 0x60, 0xb1, 0x48, 0xd2, 0x62, 0x89, 0x8c, 0xa5, 0x6c, - 0x10, 0x4b, 0x3a, 0x14, 0xc6, 0xc4, 0x09, 0xae, 0x96, 0xed, 0x19, 0x43, 0x12, 0xd0, 0x7d, 0x58, - 0x68, 0x39, 0xc4, 0xa4, 0xfe, 0x90, 0xd7, 0xcf, 0xac, 0xe0, 0xa9, 0xf0, 0x09, 0x43, 0x5e, 0x43, - 0xb7, 0xa0, 0x3c, 0xb0, 0xdb, 0x01, 0x5f, 0x5e, 0xf0, 0x95, 0x06, 0x76, 0xdb, 0x67, 0xba, 0x22, - 0x93, 0x12, 0xbd, 0x17, 0xca, 0xdb, 0x33, 0x22, 0x2d, 0xe1, 0xb7, 0x60, 0x3e, 0x64, 0x2b, 0x4d, - 0xbf, 0xcd, 0x0f, 0x9e, 0x6d, 0xee, 0xf1, 0x5c, 0xfd, 0x84, 0xa5, 0x67, 0xa3, 0xaa, 0xd1, 0x94, - 0xbf, 0xd7, 0x3c, 0x3c, 0xac, 0x66, 0xf0, 0xff, 0xfb, 0x4b, 0x44, 0x72, 0x57, 0x72, 0xfa, 0x8c, - 0x92, 0xd3, 0x35, 0x99, 0xd3, 0x33, 0x41, 0x4e, 0xcf, 0x3e, 0xae, 0x40, 0x99, 0x3b, 0xe4, 0x78, - 0x64, 0xf5, 0x6c, 0x0b, 0xff, 0x5a, 0x03, 0x38, 0x7a, 0x65, 0xc9, 0x8c, 0x53, 0x87, 0x42, 0x8b, - 0x0b, 0xaf, 0x69, 0x2c, 0x80, 0x2f, 0xc7, 0xfa, 0xd8, 0x90, 0x5c, 0xe8, 0x2d, 0x28, 0xb8, 0xa3, - 0x56, 0x8b, 0xb8, 0x32, 0xbf, 0xbf, 0x16, 0xcd, 0x21, 0x22, 0xc2, 0x0d, 0xc9, 0x47, 0x97, 0xbc, - 0x30, 0x7b, 0xfd, 0x11, 0xcb, 0xf6, 0xd3, 0x97, 0x08, 0x3e, 0xfc, 0x4b, 0x0d, 0x4a, 0x4c, 0xcb, - 0x54, 0x89, 0xeb, 0x1a, 0x14, 0x99, 0x0e, 0xa4, 0x2d, 0x52, 0xd7, 0x9c, 0x11, 0x10, 0xd0, 0xff, - 0x42, 0x51, 0x1e, 0x59, 0x99, 0xbd, 0x6a, 0xf1, 0x62, 0x0f, 0x86, 0x46, 0xc0, 0x8a, 0x77, 0xe1, - 0x12, 0xf3, 0x4a, 0x8b, 0x56, 0x65, 0xd2, 0x8f, 0x6a, 0xdd, 0xa2, 0x45, 0xea, 0x16, 0x1d, 0xe6, - 0x86, 0xdd, 0x33, 0xb7, 0xd7, 0x32, 0xfb, 0x42, 0x0b, 0x7f, 0x8c, 0xbf, 0x03, 0x48, 0x15, 0x96, - 0xc6, 0x5c, 0x3c, 0x0f, 0xa5, 0x6d, 0xd3, 0xed, 0x0a, 0x95, 0xf0, 0x47, 0x50, 0xe6, 0xc3, 0x54, - 0x3e, 0x44, 0x90, 0xeb, 0x9a, 0x6e, 0x97, 0x29, 0x3e, 0x6f, 0xb0, 0xdf, 0xf8, 0x12, 0x2c, 0x1c, - 0x5a, 0xe6, 0xd0, 0xed, 0xda, 0x32, 0xb9, 0xd2, 0xaa, 0xb4, 0x1a, 0xd0, 0x52, 0x21, 0xde, 0x83, - 0x05, 0x87, 0x0c, 0xcc, 0x9e, 0xd5, 0xb3, 0x3a, 0xc7, 0x27, 0x67, 0x1e, 0x71, 0x45, 0xd1, 0x5a, - 0xf1, 0xc9, 0x8f, 0x29, 0x95, 0xaa, 0x76, 0xd2, 0xb7, 0x4f, 0x44, 0x88, 0xb3, 0xdf, 0xf8, 0x37, - 0x1a, 0x94, 0x3f, 0x34, 0xbd, 0x96, 0xf4, 0x02, 0xda, 0x81, 0x8a, 0x1f, 0xd8, 0x8c, 0x22, 0x74, - 0x89, 0x64, 0x78, 0xb6, 0x66, 0x4b, 0x04, 0xba, 0xcc, 0xf0, 0xf3, 0x2d, 0x95, 0xc0, 0x44, 0x99, - 0x56, 0x8b, 0xf4, 0x7d, 0x51, 0x99, 0x64, 0x51, 0x8c, 0x51, 0x15, 0xa5, 0x12, 0x1e, 0x2f, 0x04, - 0xb7, 0x1f, 0x0f, 0xcb, 0x2f, 0x33, 0x80, 0x26, 0x75, 0xf8, 0xa6, 0x05, 0xc1, 0x1d, 0xa8, 0xb8, - 0x9e, 0xe9, 0x78, 0xc7, 0x91, 0x92, 0x7e, 0x9e, 0x51, 0xfd, 0xe4, 0x74, 0x0f, 0x16, 0x86, 0x8e, - 0xdd, 0x71, 0x88, 0xeb, 0x1e, 0x5b, 0xb6, 0xd7, 0x7b, 0x71, 0x26, 0xaa, 0xa1, 0x8a, 0x24, 0xef, - 0x33, 0x2a, 0x6a, 0x42, 0xe1, 0x45, 0xaf, 0xef, 0x11, 0xc7, 0xad, 0xcd, 0xae, 0x66, 0xd7, 0x2a, - 0x1b, 0x0f, 0xcf, 0xf3, 0xda, 0xfa, 0x7b, 0x8c, 0xff, 0xe8, 0x6c, 0x48, 0x0c, 0xb9, 0x56, 0xad, - 0x53, 0xf2, 0xa1, 0x3a, 0xe5, 0x0e, 0x40, 0xc0, 0x4f, 0xb3, 0xd6, 0xfe, 0xc1, 0xd3, 0x67, 0x47, - 0xd5, 0x19, 0x54, 0x86, 0xb9, 0xfd, 0x83, 0x46, 0x73, 0xaf, 0x49, 0xf3, 0x1a, 0xae, 0x4b, 0xdf, - 0xa8, 0x3e, 0x44, 0xcb, 0x30, 0xf7, 0x92, 0x52, 0xe5, 0x9b, 0x27, 0x6b, 0x14, 0xd8, 0x78, 0xa7, - 0x8d, 0xff, 0xaa, 0xc1, 0xbc, 0x38, 0x05, 0xa9, 0x8e, 0xa2, 0x0a, 0x91, 0x09, 0x41, 0xd0, 0xa2, - 0x88, 0x9f, 0x8e, 0xb6, 0xa8, 0xbd, 0xe4, 0x90, 0x86, 0x3b, 0xdf, 0x6c, 0xd2, 0x16, 0x6e, 0xf5, - 0xc7, 0xe8, 0x3e, 0x54, 0x5b, 0x3c, 0xdc, 0x23, 0xf7, 0x8c, 0xb1, 0x20, 0xe8, 0xfe, 0x26, 0xdd, - 0x81, 0x3c, 0x19, 0x13, 0xcb, 0x73, 0x6b, 0x25, 0x96, 0x9b, 0xe6, 0x65, 0x65, 0xd5, 0xa4, 0x54, - 0x43, 0x4c, 0xe2, 0xff, 0x81, 0x4b, 0x7b, 0xb4, 0xb4, 0x7d, 0xe2, 0x98, 0x96, 0x5a, 0x24, 0x1f, - 0x1d, 0xed, 0x09, 0xaf, 0x64, 0xbd, 0xa3, 0x3d, 0x54, 0x81, 0xcc, 0x4e, 0x43, 0xd8, 0x90, 0xe9, - 0x35, 0xf0, 0x67, 0x1a, 0x20, 0x75, 0x5d, 0x2a, 0x37, 0x45, 0x84, 0x4b, 0xf8, 0x6c, 0x00, 0xbf, - 0x04, 0xb3, 0xc4, 0x71, 0x6c, 0x87, 0x39, 0xa4, 0x68, 0xf0, 0x01, 0xbe, 0x2d, 0x74, 0x30, 0xc8, - 0xd8, 0x3e, 0xf5, 0xcf, 0x3c, 0x97, 0xa6, 0xf9, 0xaa, 0xee, 0xc2, 0x62, 0x88, 0x2b, 0x55, 0x8e, - 0xbc, 0x07, 0x97, 0x99, 0xb0, 0x5d, 0x42, 0x86, 0x9b, 0xfd, 0xde, 0x38, 0x11, 0x75, 0x08, 0x57, - 0xa2, 0x8c, 0xdf, 0xae, 0x8f, 0x70, 0x17, 0xf2, 0xef, 0xb3, 0x57, 0xb9, 0xa2, 0x4b, 0x8e, 0xf1, - 0x22, 0xc8, 0x59, 0xe6, 0x80, 0x3f, 0x70, 0x8a, 0x06, 0xfb, 0xcd, 0x2e, 0x15, 0x42, 0x9c, 0x67, - 0xc6, 0x1e, 0xbf, 0xbc, 0x8a, 0x86, 0x3f, 0x46, 0x2b, 0x00, 0xad, 0x7e, 0x8f, 0x58, 0x1e, 0x9b, - 0xcd, 0xb1, 0x59, 0x85, 0x82, 0xd7, 0xa1, 0xca, 0x91, 0x36, 0xdb, 0x6d, 0xe5, 0x02, 0xf3, 0xe5, - 0x69, 0x61, 0x79, 0xf8, 0x25, 0x5c, 0x52, 0xf8, 0x53, 0xb9, 0xe1, 0x75, 0xc8, 0xf3, 0xd6, 0x83, - 0xc8, 0x9d, 0x4b, 0xe1, 0x55, 0x1c, 0xc6, 0x10, 0x3c, 0xf8, 0x0e, 0x2c, 0x0a, 0x0a, 0x19, 0xd8, - 0x71, 0x7b, 0xc5, 0xfc, 0x83, 0xf7, 0x60, 0x29, 0xcc, 0x96, 0xea, 0x88, 0x6c, 0x4a, 0xd0, 0x67, - 0xc3, 0xb6, 0x92, 0x8a, 0xa3, 0x9b, 0xa2, 0x3a, 0x2c, 0x13, 0x71, 0x98, 0xaf, 0x90, 0x14, 0x91, - 0x4a, 0xa1, 0x45, 0xe9, 0xfe, 0xbd, 0x9e, 0xeb, 0x5f, 0xb8, 0x9f, 0x02, 0x52, 0x89, 0xa9, 0x36, - 0x65, 0x1d, 0x0a, 0xdc, 0xe1, 0xb2, 0xa6, 0x8b, 0xdf, 0x15, 0xc9, 0x44, 0x15, 0x6a, 0x90, 0x17, - 0x8e, 0xd9, 0x19, 0x10, 0x3f, 0xe7, 0xd0, 0x4a, 0x46, 0x25, 0xa6, 0xb2, 0xf8, 0x0f, 0x1a, 0x94, - 0x37, 0xfb, 0xa6, 0x33, 0x90, 0xce, 0x7f, 0x17, 0xf2, 0xbc, 0x44, 0x12, 0xcf, 0x88, 0xbb, 0x61, - 0x31, 0x2a, 0x2f, 0x1f, 0x6c, 0xf2, 0x82, 0x4a, 0xac, 0xa2, 0x9b, 0x25, 0x3a, 0x5e, 0x8d, 0x48, - 0x07, 0xac, 0x81, 0xde, 0x80, 0x59, 0x93, 0x2e, 0x61, 0xb1, 0x58, 0x89, 0x16, 0xa7, 0x4c, 0x1a, - 0xbb, 0xce, 0x38, 0x17, 0x7e, 0x07, 0x4a, 0x0a, 0x02, 0xad, 0xb9, 0x9f, 0x34, 0xc5, 0x95, 0xb5, - 0xb9, 0x75, 0xb4, 0xf3, 0x9c, 0x97, 0xe2, 0x15, 0x80, 0x46, 0xd3, 0x1f, 0x67, 0xf0, 0x47, 0x62, - 0x95, 0x88, 0x70, 0x55, 0x1f, 0x2d, 0x49, 0x9f, 0xcc, 0x85, 0xf4, 0x79, 0x05, 0xf3, 0xc2, 0xfc, - 0x54, 0x67, 0xe0, 0x2d, 0xc8, 0x33, 0x79, 0xf2, 0x08, 0x2c, 0xc7, 0xc0, 0xca, 0xe8, 0xe4, 0x8c, - 0x78, 0x01, 0xe6, 0x0f, 0x3d, 0xd3, 0x1b, 0xb9, 0xf2, 0x08, 0xfc, 0x5e, 0x83, 0x8a, 0xa4, 0xa4, - 0xed, 0x38, 0xc8, 0x97, 0x1a, 0xcf, 0x79, 0xfe, 0x3b, 0xed, 0x0a, 0xe4, 0xdb, 0x27, 0x87, 0xbd, - 0x4f, 0x65, 0x5f, 0x47, 0x8c, 0x28, 0xbd, 0xcf, 0x71, 0x78, 0x9f, 0x52, 0x8c, 0xe8, 0x13, 0xc0, - 0x31, 0x5f, 0x78, 0x3b, 0x56, 0x9b, 0xbc, 0x62, 0x37, 0x6d, 0xce, 0x08, 0x08, 0xac, 0x6a, 0x17, - 0xfd, 0x4c, 0x56, 0x99, 0xa8, 0xfd, 0xcd, 0x45, 0xb8, 0xb4, 0x39, 0xf2, 0xba, 0x4d, 0xcb, 0x3c, - 0xe9, 0xcb, 0x24, 0x80, 0x97, 0x00, 0x51, 0x62, 0xa3, 0xe7, 0xaa, 0xd4, 0x26, 0x2c, 0x52, 0x2a, - 0xb1, 0xbc, 0x5e, 0x4b, 0xc9, 0x18, 0x32, 0x6d, 0x6b, 0x91, 0xb4, 0x6d, 0xba, 0xee, 0x4b, 0xdb, - 0x69, 0x0b, 0xd3, 0xfc, 0x31, 0x6e, 0x70, 0xe1, 0xcf, 0xdc, 0x50, 0x62, 0xfe, 0xa6, 0x52, 0xd6, - 0x02, 0x29, 0x4f, 0x88, 0x37, 0x45, 0x0a, 0x7e, 0x08, 0x97, 0x25, 0xa7, 0x78, 0xca, 0x4f, 0x61, - 0x3e, 0x80, 0xeb, 0x92, 0x79, 0xab, 0x4b, 0xeb, 0xcd, 0xa7, 0x02, 0xf0, 0x3f, 0xd5, 0xf3, 0x31, - 0xd4, 0x7c, 0x3d, 0x59, 0x0d, 0x62, 0xf7, 0x55, 0x05, 0x46, 0xae, 0x38, 0x33, 0x45, 0x83, 0xfd, - 0xa6, 0x34, 0xc7, 0xee, 0xfb, 0x97, 0x20, 0xfd, 0x8d, 0xb7, 0x60, 0x59, 0xca, 0x10, 0xd5, 0x41, - 0x58, 0xc8, 0x84, 0x42, 0x71, 0x42, 0x84, 0xc3, 0xe8, 0xd2, 0xe9, 0x6e, 0x57, 0x39, 0xc3, 0xae, - 0x65, 0x32, 0x35, 0x45, 0xe6, 0x65, 0x7e, 0x22, 0xa8, 0x62, 0x6a, 0xd2, 0x16, 0x64, 0x2a, 0x40, - 0x25, 0x8b, 0x8d, 0xa0, 0xe4, 0x89, 0x8d, 0x98, 0x10, 0xfd, 0x31, 0xac, 0xf8, 0x4a, 0x50, 0xbf, - 0x3d, 0x25, 0xce, 0xa0, 0xe7, 0xba, 0xca, 0x5b, 0x34, 0xce, 0xf0, 0xbb, 0x90, 0x1b, 0x12, 0x91, - 0x53, 0x4a, 0x1b, 0x68, 0x9d, 0x7f, 0x75, 0x58, 0x57, 0x16, 0xb3, 0x79, 0xdc, 0x86, 0x1b, 0x52, - 0x3a, 0xf7, 0x68, 0xac, 0xf8, 0xa8, 0x52, 0xf2, 0x9d, 0xc2, 0xdd, 0x3a, 0xf9, 0x4e, 0xc9, 0xf2, - 0xbd, 0x97, 0xef, 0x14, 0x7a, 0x57, 0xa8, 0xb1, 0x95, 0xea, 0xae, 0xd8, 0xe5, 0x3e, 0xf5, 0x43, - 0x32, 0x95, 0xb0, 0x13, 0x58, 0x0a, 0x47, 0x72, 0xaa, 0x34, 0xb6, 0x04, 0xb3, 0x9e, 0x7d, 0x4a, - 0x64, 0x12, 0xe3, 0x03, 0xa9, 0xb0, 0x1f, 0xe6, 0xa9, 0x14, 0x36, 0x03, 0x61, 0xec, 0x48, 0xa6, - 0xd5, 0x97, 0xee, 0xa6, 0xac, 0x67, 0xf8, 0x00, 0xef, 0xc3, 0x95, 0x68, 0x9a, 0x48, 0xa5, 0xf2, - 0x73, 0x7e, 0x80, 0xe3, 0x32, 0x49, 0x2a, 0xb9, 0x1f, 0x04, 0xc9, 0x40, 0x49, 0x28, 0xa9, 0x44, - 0x1a, 0xa0, 0xc7, 0xe5, 0x97, 0xff, 0xc6, 0x79, 0xf5, 0xd3, 0x4d, 0x2a, 0x61, 0x6e, 0x20, 0x2c, - 0xfd, 0xf6, 0x07, 0x39, 0x22, 0x3b, 0x35, 0x47, 0x88, 0x20, 0x09, 0xb2, 0xd8, 0xb7, 0x70, 0xe8, - 0x04, 0x46, 0x90, 0x40, 0xd3, 0x62, 0xd0, 0x3b, 0xc4, 0xc7, 0x60, 0x03, 0x79, 0xb0, 0xd5, 0xb4, - 0x9b, 0x6a, 0x33, 0x3e, 0x0c, 0x72, 0xe7, 0x44, 0x66, 0x4e, 0x25, 0xf8, 0x23, 0x58, 0x4d, 0x4e, - 0xca, 0x69, 0x24, 0x3f, 0xc0, 0x50, 0xf4, 0x0b, 0x4a, 0xe5, 0x2b, 0x63, 0x09, 0x0a, 0xfb, 0x07, - 0x87, 0x4f, 0x37, 0xb7, 0x9a, 0x55, 0x6d, 0xe3, 0x9f, 0x59, 0xc8, 0xec, 0x3e, 0x47, 0xdf, 0x83, - 0x59, 0xfe, 0x0d, 0x62, 0xca, 0x27, 0x1a, 0x7d, 0xda, 0xd7, 0x0c, 0x7c, 0xed, 0xb3, 0x3f, 0xfe, - 0xe5, 0x8b, 0xcc, 0x15, 0x7c, 0xa9, 0x3e, 0x7e, 0xdb, 0xec, 0x0f, 0xbb, 0x66, 0xfd, 0x74, 0x5c, - 0x67, 0x77, 0xc2, 0x23, 0xed, 0x01, 0x7a, 0x0e, 0xd9, 0xa7, 0x23, 0x0f, 0x25, 0x7e, 0xbf, 0xd1, - 0x93, 0xbf, 0x72, 0x60, 0x9d, 0x49, 0x5e, 0xc2, 0x0b, 0xaa, 0xe4, 0xe1, 0xc8, 0xa3, 0x72, 0xc7, - 0x50, 0x52, 0x3e, 0x54, 0xa0, 0x73, 0xbf, 0xec, 0xe8, 0xe7, 0x7f, 0x04, 0xc1, 0x98, 0xe1, 0x5d, - 0xc3, 0xaf, 0xa9, 0x78, 0xfc, 0x7b, 0x8a, 0x6a, 0xcf, 0xd1, 0x2b, 0x2b, 0x6a, 0x4f, 0xd0, 0x7a, - 0x8f, 0xda, 0xa3, 0xb4, 0xbb, 0xe3, 0xed, 0xf1, 0x5e, 0x59, 0x54, 0xae, 0x2d, 0x3e, 0xae, 0xb4, - 0x3c, 0x74, 0x23, 0xa6, 0x57, 0xaf, 0x76, 0xa5, 0xf5, 0xd5, 0x64, 0x06, 0x81, 0x74, 0x93, 0x21, - 0x5d, 0xc5, 0x57, 0x54, 0xa4, 0x96, 0xcf, 0xf7, 0x48, 0x7b, 0xb0, 0xd1, 0x85, 0x59, 0xd6, 0x4b, - 0x43, 0xc7, 0xf2, 0x87, 0x1e, 0xd3, 0x05, 0x4c, 0x38, 0x01, 0xa1, 0x2e, 0x1c, 0x5e, 0x66, 0x68, - 0x8b, 0xb8, 0xe2, 0xa3, 0xb1, 0x76, 0xda, 0x23, 0xed, 0xc1, 0x9a, 0xf6, 0xa6, 0xb6, 0xf1, 0x8f, - 0x0c, 0xcc, 0xb2, 0xa6, 0x0b, 0x1a, 0x02, 0x04, 0xdd, 0xa9, 0xa8, 0x9d, 0x13, 0xfd, 0xae, 0xa8, - 0x9d, 0x93, 0x8d, 0x2d, 0x7c, 0x83, 0x21, 0x2f, 0xe3, 0x25, 0x1f, 0x99, 0x7d, 0x10, 0xae, 0x77, - 0x28, 0x17, 0x75, 0xeb, 0x4b, 0x28, 0x29, 0x5d, 0x26, 0x14, 0x27, 0x31, 0xd4, 0xa6, 0x8a, 0x1e, - 0x93, 0x98, 0x16, 0x15, 0xbe, 0xc5, 0x40, 0xaf, 0xe3, 0x9a, 0xea, 0x5c, 0x8e, 0xeb, 0x30, 0x4e, - 0x0a, 0xfc, 0x63, 0x0d, 0x2a, 0xe1, 0x4e, 0x13, 0xba, 0x15, 0x23, 0x3a, 0xda, 0xb0, 0xd2, 0x6f, - 0x4f, 0x67, 0x4a, 0x54, 0x81, 0xe3, 0x9f, 0x12, 0x32, 0x34, 0x29, 0xa7, 0xf4, 0xfd, 0xbf, 0xb2, - 0x50, 0xd8, 0xe2, 0x7f, 0x32, 0x82, 0x3c, 0x28, 0xfa, 0xfd, 0x1e, 0xb4, 0x12, 0xd7, 0x0b, 0x08, - 0x0a, 0x65, 0xfd, 0x46, 0xe2, 0xbc, 0x50, 0xe1, 0x2e, 0x53, 0x61, 0x15, 0x5f, 0xf5, 0x55, 0x10, - 0x7f, 0x9a, 0x52, 0xe7, 0x4f, 0xde, 0xba, 0xd9, 0x6e, 0x53, 0x47, 0xfc, 0x48, 0x83, 0xb2, 0xda, - 0xc6, 0x41, 0x37, 0x63, 0xbb, 0x10, 0x6a, 0x27, 0x48, 0xc7, 0xd3, 0x58, 0x04, 0xfe, 0x7d, 0x86, - 0x7f, 0x0b, 0xaf, 0x24, 0xe1, 0x3b, 0x8c, 0x3f, 0xac, 0x02, 0x6f, 0xdc, 0xc4, 0xab, 0x10, 0xea, - 0x0b, 0xc5, 0xab, 0x10, 0xee, 0xfb, 0x9c, 0xaf, 0xc2, 0x88, 0xf1, 0x53, 0x15, 0x5e, 0x01, 0x04, - 0x7d, 0x1d, 0x14, 0xeb, 0x5c, 0xe5, 0xe9, 0x10, 0x3d, 0xf9, 0x93, 0x2d, 0x21, 0x7c, 0x8f, 0x61, - 0xdf, 0xc4, 0xd7, 0x92, 0xb0, 0xfb, 0x3d, 0x97, 0x46, 0xc0, 0xc6, 0x6f, 0x73, 0x50, 0x7a, 0xdf, - 0xec, 0x59, 0x1e, 0xb1, 0x4c, 0xab, 0x45, 0x50, 0x07, 0x66, 0xd9, 0xdd, 0x10, 0x0d, 0x77, 0xb5, - 0xd9, 0x12, 0x0d, 0xf7, 0x50, 0x27, 0x02, 0xdf, 0x61, 0xd0, 0x37, 0xb0, 0xee, 0x43, 0x0f, 0x02, - 0xf9, 0x75, 0xd6, 0x45, 0xa0, 0x26, 0x9f, 0x42, 0x9e, 0x77, 0x0d, 0x50, 0x44, 0x5a, 0xa8, 0xbb, - 0xa0, 0x5f, 0x8b, 0x9f, 0x4c, 0x3c, 0x65, 0x2a, 0x96, 0xcb, 0x98, 0x29, 0xd8, 0xf7, 0x01, 0x82, - 0x36, 0x55, 0xd4, 0xbf, 0x13, 0x5d, 0x2d, 0x7d, 0x35, 0x99, 0x41, 0x00, 0x3f, 0x60, 0xc0, 0xb7, - 0xf1, 0x8d, 0x58, 0xe0, 0xb6, 0xbf, 0x80, 0x82, 0xb7, 0x20, 0xb7, 0x6d, 0xba, 0x5d, 0x14, 0x49, - 0xfd, 0xca, 0x57, 0x3b, 0x5d, 0x8f, 0x9b, 0x12, 0x50, 0xb7, 0x19, 0xd4, 0x0a, 0x5e, 0x8e, 0x85, - 0xea, 0x9a, 0x2e, 0xcd, 0xa4, 0x68, 0x04, 0x73, 0xf2, 0x4b, 0x1c, 0xba, 0x1e, 0xf1, 0x59, 0xf8, - 0xab, 0x9d, 0xbe, 0x92, 0x34, 0x2d, 0x00, 0xd7, 0x18, 0x20, 0xc6, 0xd7, 0xe3, 0x9d, 0x2a, 0xd8, - 0x1f, 0x69, 0x0f, 0xde, 0xd4, 0x36, 0x7e, 0x5a, 0x85, 0x1c, 0xad, 0x52, 0x68, 0xee, 0x0e, 0x1e, - 0x77, 0x51, 0x0f, 0x4f, 0xb4, 0x54, 0xa2, 0x1e, 0x9e, 0x7c, 0x17, 0xc6, 0xe4, 0x6e, 0xf6, 0x87, - 0x73, 0x84, 0x71, 0x51, 0x8b, 0x3d, 0x28, 0x29, 0x4f, 0x40, 0x14, 0x23, 0x31, 0xdc, 0xb0, 0x89, - 0xe6, 0xee, 0x98, 0xf7, 0x23, 0x5e, 0x65, 0xa0, 0x3a, 0xbe, 0x1c, 0x06, 0x6d, 0x73, 0x36, 0x8a, - 0xfa, 0x03, 0x28, 0xab, 0x6f, 0x45, 0x14, 0x23, 0x34, 0xd2, 0x11, 0x8a, 0xe6, 0x8a, 0xb8, 0xa7, - 0x66, 0x4c, 0xd0, 0xf8, 0x7f, 0x26, 0x28, 0x79, 0x29, 0xfa, 0x27, 0x50, 0x10, 0x2f, 0xc8, 0x38, - 0x7b, 0xc3, 0x3d, 0xa4, 0x38, 0x7b, 0x23, 0xcf, 0xcf, 0x98, 0x42, 0x80, 0xc1, 0xd2, 0x4a, 0x59, - 0x26, 0x68, 0x01, 0xf9, 0x84, 0x78, 0x49, 0x90, 0x41, 0x57, 0x24, 0x09, 0x52, 0x79, 0xa5, 0x4c, - 0x85, 0xec, 0x10, 0x4f, 0x9c, 0x65, 0xf9, 0x04, 0x40, 0x09, 0x12, 0xd5, 0x6c, 0x88, 0xa7, 0xb1, - 0x24, 0xd6, 0x6e, 0x01, 0xaa, 0x48, 0x85, 0xe8, 0x87, 0x00, 0xc1, 0x73, 0x37, 0x7a, 0x1d, 0xc7, - 0xf6, 0xcc, 0xa2, 0xd7, 0x71, 0xfc, 0x8b, 0x39, 0x26, 0x82, 0x03, 0x70, 0x5e, 0x3f, 0x52, 0xf8, - 0x9f, 0x6b, 0x80, 0x26, 0x9f, 0xc7, 0xe8, 0x61, 0x3c, 0x44, 0x6c, 0x3b, 0x4e, 0x7f, 0xfd, 0x62, - 0xcc, 0x89, 0xd9, 0x33, 0xd0, 0xab, 0xc5, 0x96, 0x0c, 0x5f, 0x52, 0xcd, 0x3e, 0xd7, 0x60, 0x3e, - 0xf4, 0xc0, 0x46, 0x77, 0x13, 0xf6, 0x39, 0xd2, 0xd2, 0xd3, 0xef, 0x9d, 0xcb, 0x97, 0x58, 0xb1, - 0x28, 0xa7, 0x42, 0x56, 0x6b, 0x3f, 0xd1, 0xa0, 0x12, 0x7e, 0x95, 0xa3, 0x04, 0x80, 0x89, 0xbe, - 0xa0, 0xbe, 0x76, 0x3e, 0xe3, 0x05, 0x76, 0x2b, 0x28, 0xe0, 0x3e, 0x81, 0x82, 0x78, 0xcc, 0xc7, - 0x85, 0x45, 0xb8, 0xad, 0x18, 0x17, 0x16, 0x91, 0x4e, 0x40, 0x52, 0x58, 0xd0, 0x77, 0xb1, 0x12, - 0x89, 0xe2, 0xc9, 0x9f, 0x04, 0x39, 0x3d, 0x12, 0x23, 0xfd, 0x82, 0xa9, 0x90, 0x41, 0x24, 0xca, - 0x07, 0x3f, 0x4a, 0x90, 0x78, 0x4e, 0x24, 0x46, 0xfb, 0x05, 0x49, 0x91, 0xc8, 0x50, 0x95, 0x48, - 0x0c, 0xde, 0xe7, 0x71, 0x91, 0x38, 0xd1, 0x34, 0x8d, 0x8b, 0xc4, 0xc9, 0x27, 0x7e, 0xd2, 0xde, - 0x32, 0xf0, 0x50, 0x24, 0x2e, 0xc6, 0xbc, 0xe7, 0xd1, 0xeb, 0x09, 0x3e, 0x8d, 0x6d, 0xc8, 0xea, - 0x6f, 0x5c, 0x90, 0x7b, 0x7a, 0x04, 0xf0, 0xdd, 0x90, 0x11, 0xf0, 0x2b, 0x0d, 0x96, 0xe2, 0x1a, - 0x02, 0x28, 0x01, 0x2c, 0xa1, 0x9b, 0xab, 0xaf, 0x5f, 0x94, 0xfd, 0x02, 0x7e, 0xf3, 0x63, 0xe2, - 0x71, 0xf5, 0x77, 0x5f, 0xaf, 0x68, 0x5f, 0x7d, 0xbd, 0xa2, 0xfd, 0xe9, 0xeb, 0x15, 0xed, 0x17, - 0x7f, 0x5e, 0x99, 0x39, 0xc9, 0xb3, 0xbf, 0x5e, 0x7f, 0xfb, 0xdf, 0x01, 0x00, 0x00, 0xff, 0xff, - 0x66, 0x40, 0x0b, 0xdf, 0x44, 0x2f, 0x00, 0x00, + // 3337 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0xb4, 0x5b, 0x4f, 0x73, 0x1b, 0xc7, + 0xb1, 0xe7, 0x02, 0x20, 0x40, 0x34, 0x40, 0x10, 0x1a, 0x52, 0x12, 0xb8, 0x92, 0x28, 0x6a, 0xf4, + 0x8f, 0x92, 0x6c, 0xd2, 0xa6, 0xfd, 0xde, 0x41, 0xcf, 0xe5, 0x2a, 0x8a, 0x84, 0x45, 0x3e, 0xd2, + 0xa4, 0xbc, 0xa4, 0x64, 0xbf, 0x2a, 0xd7, 0x63, 0x2d, 0x81, 0x11, 0xb0, 0x45, 0x60, 0x17, 0xde, + 0x5d, 0x40, 0xa2, 0x93, 0x54, 0xa5, 0x9c, 0xb8, 0x52, 0xc9, 0x31, 0x3e, 0x24, 0x71, 0x8e, 0xa9, + 0x7c, 0x84, 0xdc, 0xf2, 0x01, 0x52, 0xb9, 0xc4, 0x55, 0xf9, 0x02, 0x29, 0x27, 0x87, 0x1c, 0x72, + 0xcf, 0x29, 0x95, 0xd4, 0xfc, 0xdb, 0x9d, 0x5d, 0xec, 0x82, 0x72, 0x36, 0xbe, 0x88, 0x3b, 0x33, + 0x3d, 0xfd, 0xeb, 0xee, 0x99, 0xee, 0xe9, 0xe9, 0x81, 0xa0, 0xec, 0x0e, 0x5a, 0xab, 0x03, 0xd7, + 0xf1, 0x1d, 0x54, 0x25, 0x7e, 0xab, 0xed, 0x11, 0x77, 0x44, 0xdc, 0xc1, 0x89, 0xbe, 0xd0, 0x71, + 0x3a, 0x0e, 0x1b, 0x58, 0xa3, 0x5f, 0x9c, 0x46, 0x5f, 0xa4, 0x34, 0x6b, 0xfd, 0x51, 0xab, 0xc5, + 0xfe, 0x19, 0x9c, 0xac, 0x9d, 0x8e, 0xc4, 0xd0, 0x15, 0x36, 0x64, 0x0e, 0xfd, 0x2e, 0xfb, 0x67, + 0x70, 0xc2, 0xfe, 0x88, 0xc1, 0xab, 0x1d, 0xc7, 0xe9, 0xf4, 0xc8, 0x9a, 0x39, 0xb0, 0xd6, 0x4c, + 0xdb, 0x76, 0x7c, 0xd3, 0xb7, 0x1c, 0xdb, 0xe3, 0xa3, 0xf8, 0x73, 0x0d, 0x6a, 0x06, 0xf1, 0x06, + 0x8e, 0xed, 0x91, 0x6d, 0x62, 0xb6, 0x89, 0x8b, 0xae, 0x01, 0xb4, 0x7a, 0x43, 0xcf, 0x27, 0xee, + 0xb1, 0xd5, 0x6e, 0x68, 0xcb, 0xda, 0x4a, 0xc1, 0x28, 0x8b, 0x9e, 0x9d, 0x36, 0xba, 0x02, 0xe5, + 0x3e, 0xe9, 0x9f, 0xf0, 0xd1, 0x1c, 0x1b, 0x9d, 0xe1, 0x1d, 0x3b, 0x6d, 0xa4, 0xc3, 0x8c, 0x4b, + 0x46, 0x96, 0x67, 0x39, 0x76, 0x23, 0xbf, 0xac, 0xad, 0xe4, 0x8d, 0xa0, 0x4d, 0x27, 0xba, 0xe6, + 0x73, 0xff, 0xd8, 0x27, 0x6e, 0xbf, 0x51, 0xe0, 0x13, 0x69, 0xc7, 0x11, 0x71, 0xfb, 0xf8, 0xab, + 0x3c, 0x54, 0x0d, 0xd3, 0xee, 0x10, 0x83, 0x7c, 0x32, 0x24, 0x9e, 0x8f, 0xea, 0x90, 0x3f, 0x25, + 0x67, 0x0c, 0xbe, 0x6a, 0xd0, 0x4f, 0x3e, 0xdf, 0xee, 0x90, 0x63, 0x62, 0x73, 0xe0, 0x2a, 0x9d, + 0x6f, 0x77, 0x48, 0xd3, 0x6e, 0xa3, 0x05, 0x98, 0xee, 0x59, 0x7d, 0xcb, 0x17, 0xa8, 0xbc, 0x11, + 0x11, 0xa7, 0x10, 0x13, 0x67, 0x13, 0xc0, 0x73, 0x5c, 0xff, 0xd8, 0x71, 0xdb, 0xc4, 0x6d, 0x4c, + 0x2f, 0x6b, 0x2b, 0xb5, 0xf5, 0x5b, 0xab, 0xea, 0x42, 0xac, 0xaa, 0x02, 0xad, 0x1e, 0x3a, 0xae, + 0x7f, 0x40, 0x69, 0x8d, 0xb2, 0x27, 0x3f, 0xd1, 0x7b, 0x50, 0x61, 0x4c, 0x7c, 0xd3, 0xed, 0x10, + 0xbf, 0x51, 0x64, 0x5c, 0x6e, 0x9f, 0xc3, 0xe5, 0x88, 0x11, 0x1b, 0x0c, 0x9e, 0x7f, 0x23, 0x0c, + 0x55, 0x8f, 0xb8, 0x96, 0xd9, 0xb3, 0x3e, 0x35, 0x4f, 0x7a, 0xa4, 0x51, 0x5a, 0xd6, 0x56, 0x66, + 0x8c, 0x48, 0x1f, 0xd5, 0xff, 0x94, 0x9c, 0x79, 0xc7, 0x8e, 0xdd, 0x3b, 0x6b, 0xcc, 0x30, 0x82, + 0x19, 0xda, 0x71, 0x60, 0xf7, 0xce, 0xd8, 0xa2, 0x39, 0x43, 0xdb, 0xe7, 0xa3, 0x65, 0x36, 0x5a, + 0x66, 0x3d, 0x74, 0x18, 0xaf, 0x42, 0x39, 0x90, 0x1f, 0xcd, 0x40, 0x61, 0xff, 0x60, 0xbf, 0x59, + 0x9f, 0x42, 0x00, 0xc5, 0x8d, 0xc3, 0xcd, 0xe6, 0xfe, 0x56, 0x5d, 0x43, 0x15, 0x28, 0x6d, 0x35, + 0x79, 0x23, 0x87, 0x1f, 0x01, 0x84, 0x92, 0xa2, 0x12, 0xe4, 0x77, 0x9b, 0xff, 0x57, 0x9f, 0xa2, + 0x34, 0xcf, 0x9a, 0xc6, 0xe1, 0xce, 0xc1, 0x7e, 0x5d, 0xa3, 0x93, 0x37, 0x8d, 0xe6, 0xc6, 0x51, + 0xb3, 0x9e, 0xa3, 0x14, 0xef, 0x1f, 0x6c, 0xd5, 0xf3, 0xa8, 0x0c, 0xd3, 0xcf, 0x36, 0xf6, 0x9e, + 0x36, 0xeb, 0x05, 0xfc, 0x85, 0x06, 0xb3, 0x42, 0x77, 0xbe, 0xbf, 0xd0, 0xdb, 0x50, 0xec, 0xb2, + 0x3d, 0xc6, 0x96, 0xb5, 0xb2, 0x7e, 0x35, 0x66, 0xa8, 0xc8, 0x3e, 0x34, 0x04, 0x2d, 0xc2, 0x90, + 0x3f, 0x1d, 0x79, 0x8d, 0xdc, 0x72, 0x7e, 0xa5, 0xb2, 0x5e, 0x5f, 0xe5, 0x9b, 0x7f, 0x75, 0x97, + 0x9c, 0x3d, 0x33, 0x7b, 0x43, 0x62, 0xd0, 0x41, 0x84, 0xa0, 0xd0, 0x77, 0x5c, 0xc2, 0x56, 0x7f, + 0xc6, 0x60, 0xdf, 0x74, 0x4b, 0x30, 0x03, 0x88, 0x95, 0xe7, 0x0d, 0xdc, 0x02, 0x78, 0x32, 0xf4, + 0xd3, 0x77, 0xd9, 0x02, 0x4c, 0x8f, 0x28, 0x5f, 0xb1, 0xc3, 0x78, 0x83, 0x6d, 0x2f, 0x62, 0x7a, + 0x24, 0xd8, 0x5e, 0xb4, 0x81, 0x2e, 0x43, 0x69, 0xe0, 0x92, 0xd1, 0xf1, 0xe9, 0x88, 0x61, 0xcc, + 0x18, 0x45, 0xda, 0xdc, 0x1d, 0x61, 0x1b, 0x2a, 0x0c, 0x24, 0x93, 0xde, 0xf7, 0x42, 0xee, 0x39, + 0x36, 0x6d, 0x5c, 0x77, 0x89, 0xf7, 0x31, 0xa0, 0x2d, 0xd2, 0x23, 0x3e, 0xc9, 0xe2, 0x42, 0x8a, + 0x36, 0xf9, 0x88, 0x36, 0x3f, 0xd5, 0x60, 0x3e, 0xc2, 0x3e, 0x93, 0x5a, 0x0d, 0x28, 0xb5, 0x19, + 0x33, 0x2e, 0x41, 0xde, 0x90, 0x4d, 0xf4, 0x00, 0x66, 0x84, 0x00, 0x5e, 0x23, 0x9f, 0xb2, 0xda, + 0x25, 0x2e, 0x93, 0x87, 0xff, 0xa6, 0x41, 0x59, 0x28, 0x7a, 0x30, 0x40, 0x1b, 0x30, 0xeb, 0xf2, + 0xc6, 0x31, 0xd3, 0x47, 0x48, 0xa4, 0xa7, 0x7b, 0xe2, 0xf6, 0x94, 0x51, 0x15, 0x53, 0x58, 0x37, + 0xfa, 0x1f, 0xa8, 0x48, 0x16, 0x83, 0xa1, 0x2f, 0x4c, 0xde, 0x88, 0x32, 0x08, 0x77, 0xce, 0xf6, + 0x94, 0x01, 0x82, 0xfc, 0xc9, 0xd0, 0x47, 0x47, 0xb0, 0x20, 0x27, 0x73, 0x6d, 0x84, 0x18, 0x79, + 0xc6, 0x65, 0x39, 0xca, 0x65, 0x7c, 0xa9, 0xb6, 0xa7, 0x0c, 0x24, 0xe6, 0x2b, 0x83, 0x8f, 0xca, + 0x50, 0x12, 0xbd, 0xf8, 0xef, 0x1a, 0x80, 0x34, 0xe8, 0xc1, 0x00, 0x6d, 0x41, 0xcd, 0x15, 0xad, + 0x88, 0xc2, 0x57, 0x12, 0x15, 0x16, 0xeb, 0x30, 0x65, 0xcc, 0xca, 0x49, 0x5c, 0xe5, 0x77, 0xa1, + 0x1a, 0x70, 0x09, 0x75, 0x5e, 0x4c, 0xd0, 0x39, 0xe0, 0x50, 0x91, 0x13, 0xa8, 0xd6, 0x1f, 0xc2, + 0xc5, 0x60, 0x7e, 0x82, 0xda, 0x37, 0x26, 0xa8, 0x1d, 0x30, 0x9c, 0x97, 0x1c, 0x54, 0xc5, 0x81, + 0xc6, 0x6d, 0xde, 0x8d, 0xbf, 0xcc, 0x43, 0x69, 0xd3, 0xe9, 0x0f, 0x4c, 0x97, 0xae, 0x51, 0xd1, + 0x25, 0xde, 0xb0, 0xe7, 0x33, 0x75, 0x6b, 0xeb, 0x37, 0xa3, 0x08, 0x82, 0x4c, 0xfe, 0x35, 0x18, + 0xa9, 0x21, 0xa6, 0xd0, 0xc9, 0x22, 0x4c, 0xe7, 0x5e, 0x61, 0xb2, 0x08, 0xd2, 0x62, 0x8a, 0xf4, + 0xa5, 0x7c, 0xe8, 0x4b, 0x3a, 0x94, 0x46, 0xc4, 0x0d, 0x8f, 0x96, 0xed, 0x29, 0x43, 0x76, 0xa0, + 0x7b, 0x30, 0xd7, 0x72, 0x89, 0x49, 0xed, 0x21, 0x8f, 0x9f, 0x69, 0x41, 0x53, 0xe3, 0x03, 0x86, + 0x3c, 0x86, 0x6e, 0x42, 0xb5, 0xef, 0xb4, 0x43, 0xba, 0xa2, 0xa0, 0xab, 0xf4, 0x9d, 0x76, 0x40, + 0x74, 0x49, 0x06, 0x25, 0x7a, 0x2e, 0x54, 0xb7, 0xa7, 0x44, 0x58, 0xc2, 0x6f, 0xc2, 0x6c, 0x44, + 0x57, 0x1a, 0x7e, 0x9b, 0x1f, 0x3c, 0xdd, 0xd8, 0xe3, 0xb1, 0xfa, 0x31, 0x0b, 0xcf, 0x46, 0x5d, + 0xa3, 0x21, 0x7f, 0xaf, 0x79, 0x78, 0x58, 0xcf, 0xe1, 0x77, 0x82, 0x29, 0x22, 0xb8, 0x2b, 0x31, + 0x7d, 0x4a, 0x89, 0xe9, 0x9a, 0x8c, 0xe9, 0xb9, 0x30, 0xa6, 0xe7, 0x1f, 0xd5, 0xa0, 0xca, 0x0d, + 0x72, 0x3c, 0xb4, 0x2d, 0xc7, 0xc6, 0xbf, 0xd2, 0x00, 0x8e, 0x5e, 0xda, 0x32, 0xe2, 0xac, 0x41, + 0xa9, 0xc5, 0x99, 0x37, 0x34, 0xe6, 0xc0, 0x17, 0x13, 0x6d, 0x6c, 0x48, 0x2a, 0xf4, 0x26, 0x94, + 0xbc, 0x61, 0xab, 0x45, 0x3c, 0x19, 0xdf, 0x2f, 0xc7, 0x63, 0x88, 0xf0, 0x70, 0x43, 0xd2, 0xd1, + 0x29, 0xcf, 0x4d, 0xab, 0x37, 0x64, 0xd1, 0x7e, 0xf2, 0x14, 0x41, 0x87, 0x7f, 0xa1, 0x41, 0x85, + 0x49, 0x99, 0x29, 0x70, 0x5d, 0x85, 0x32, 0x93, 0x81, 0xb4, 0x45, 0xe8, 0x9a, 0x31, 0xc2, 0x0e, + 0xf4, 0xdf, 0x50, 0x96, 0x5b, 0x56, 0x46, 0xaf, 0x46, 0x32, 0xdb, 0x83, 0x81, 0x11, 0x92, 0xe2, + 0x5d, 0xb8, 0xc0, 0xac, 0xd2, 0xa2, 0x59, 0x99, 0xb4, 0xa3, 0x9a, 0xb7, 0x68, 0xb1, 0xbc, 0x45, + 0x87, 0x99, 0x41, 0xf7, 0xcc, 0xb3, 0x5a, 0x66, 0x4f, 0x48, 0x11, 0xb4, 0xf1, 0xff, 0x02, 0x52, + 0x99, 0x65, 0x51, 0x17, 0xcf, 0x42, 0x65, 0xdb, 0xf4, 0xba, 0x42, 0x24, 0xfc, 0x11, 0x54, 0x79, + 0x33, 0x93, 0x0d, 0x11, 0x14, 0xba, 0xa6, 0xd7, 0x65, 0x82, 0xcf, 0x1a, 0xec, 0x1b, 0x5f, 0x80, + 0xb9, 0x43, 0xdb, 0x1c, 0x78, 0x5d, 0x47, 0x06, 0x57, 0x9a, 0x95, 0xd6, 0xc3, 0xbe, 0x4c, 0x88, + 0x77, 0x61, 0xce, 0x25, 0x7d, 0xd3, 0xb2, 0x2d, 0xbb, 0x73, 0x7c, 0x72, 0xe6, 0x13, 0x4f, 0x24, + 0xad, 0xb5, 0xa0, 0xfb, 0x11, 0xed, 0xa5, 0xa2, 0x9d, 0xf4, 0x9c, 0x13, 0xe1, 0xe2, 0xec, 0x1b, + 0xff, 0x46, 0x83, 0xea, 0x87, 0xa6, 0xdf, 0x92, 0x56, 0x40, 0x3b, 0x50, 0x0b, 0x1c, 0x9b, 0xf5, + 0x08, 0x59, 0x62, 0x11, 0x9e, 0xcd, 0xd9, 0x14, 0x8e, 0x2e, 0x23, 0xfc, 0x6c, 0x4b, 0xed, 0x60, + 0xac, 0x4c, 0xbb, 0x45, 0x7a, 0x01, 0xab, 0x5c, 0x3a, 0x2b, 0x46, 0xa8, 0xb2, 0x52, 0x3b, 0x1e, + 0xcd, 0x85, 0xa7, 0x1f, 0x77, 0xcb, 0x2f, 0x73, 0x80, 0xc6, 0x65, 0xf8, 0xa6, 0x09, 0xc1, 0x6d, + 0xa8, 0x79, 0xbe, 0xe9, 0xfa, 0xc7, 0xb1, 0x94, 0x7e, 0x96, 0xf5, 0x06, 0xc1, 0xe9, 0x2e, 0xcc, + 0x0d, 0x5c, 0xa7, 0xe3, 0x12, 0xcf, 0x3b, 0xb6, 0x1d, 0xdf, 0x7a, 0x7e, 0x26, 0xb2, 0xa1, 0x9a, + 0xec, 0xde, 0x67, 0xbd, 0xa8, 0x09, 0xa5, 0xe7, 0x56, 0xcf, 0x27, 0xae, 0xd7, 0x98, 0x5e, 0xce, + 0xaf, 0xd4, 0xd6, 0x1f, 0x9c, 0x67, 0xb5, 0xd5, 0xf7, 0x18, 0xfd, 0xd1, 0xd9, 0x80, 0x18, 0x72, + 0xae, 0x9a, 0xa7, 0x14, 0x23, 0x79, 0xca, 0x6d, 0x80, 0x90, 0x9e, 0x46, 0xad, 0xfd, 0x83, 0x27, + 0x4f, 0x8f, 0xea, 0x53, 0xa8, 0x0a, 0x33, 0xfb, 0x07, 0x5b, 0xcd, 0xbd, 0x26, 0x8d, 0x6b, 0x78, + 0x4d, 0xda, 0x46, 0xb5, 0x21, 0x5a, 0x84, 0x99, 0x17, 0xb4, 0x57, 0xde, 0x79, 0xf2, 0x46, 0x89, + 0xb5, 0x77, 0xda, 0xf8, 0xaf, 0x1a, 0xcc, 0x8a, 0x5d, 0x90, 0x69, 0x2b, 0xaa, 0x10, 0xb9, 0x08, + 0x04, 0x4d, 0x8a, 0xf8, 0xee, 0x68, 0x8b, 0xdc, 0x4b, 0x36, 0xa9, 0xbb, 0xf3, 0xc5, 0x26, 0x6d, + 0x61, 0xd6, 0xa0, 0x8d, 0xee, 0x41, 0xbd, 0xc5, 0xdd, 0x3d, 0x76, 0xce, 0x18, 0x73, 0xa2, 0x3f, + 0x58, 0xa4, 0xdb, 0x50, 0x24, 0x23, 0x62, 0xfb, 0x5e, 0xa3, 0xc2, 0x62, 0xd3, 0xac, 0xcc, 0xac, + 0x9a, 0xb4, 0xd7, 0x10, 0x83, 0xf8, 0xbf, 0xe0, 0xc2, 0x1e, 0x4d, 0x6d, 0x1f, 0xbb, 0xa6, 0xad, + 0x26, 0xc9, 0x47, 0x47, 0x7b, 0xc2, 0x2a, 0x79, 0xff, 0x68, 0x0f, 0xd5, 0x20, 0xb7, 0xb3, 0x25, + 0x74, 0xc8, 0x59, 0x5b, 0xf8, 0x33, 0x0d, 0x90, 0x3a, 0x2f, 0x93, 0x99, 0x62, 0xcc, 0x25, 0x7c, + 0x3e, 0x84, 0x5f, 0x80, 0x69, 0xe2, 0xba, 0x8e, 0xcb, 0x0c, 0x52, 0x36, 0x78, 0x03, 0xdf, 0x12, + 0x32, 0x18, 0x64, 0xe4, 0x9c, 0x06, 0x7b, 0x9e, 0x73, 0xd3, 0x02, 0x51, 0x77, 0x61, 0x3e, 0x42, + 0x95, 0x29, 0x46, 0xde, 0x85, 0x8b, 0x8c, 0xd9, 0x2e, 0x21, 0x83, 0x8d, 0x9e, 0x35, 0x4a, 0x45, + 0x1d, 0xc0, 0xa5, 0x38, 0xe1, 0xb7, 0x6b, 0x23, 0xfc, 0x8e, 0x40, 0x3c, 0xb2, 0xfa, 0xe4, 0xc8, + 0xd9, 0x4b, 0x97, 0x8d, 0x06, 0x3e, 0x7a, 0x8d, 0x14, 0x87, 0x09, 0xfb, 0xc6, 0xbf, 0xd6, 0xe0, + 0xf2, 0xd8, 0xf4, 0x6f, 0x79, 0x55, 0x97, 0x00, 0x3a, 0x74, 0xfb, 0x90, 0x36, 0x1d, 0xe0, 0x97, + 0x36, 0xa5, 0x27, 0x90, 0x93, 0xc6, 0x8e, 0xaa, 0x90, 0xb3, 0x0b, 0xc5, 0xf7, 0x59, 0xed, 0x41, + 0xd1, 0xaa, 0x20, 0xb5, 0xb2, 0xcd, 0x3e, 0xbf, 0xc6, 0x95, 0x0d, 0xf6, 0xcd, 0x8e, 0x4e, 0x42, + 0xdc, 0xa7, 0xc6, 0x1e, 0x3f, 0xa2, 0xcb, 0x46, 0xd0, 0xa6, 0xe8, 0xad, 0x9e, 0x45, 0x6c, 0x9f, + 0x8d, 0x16, 0xd8, 0xa8, 0xd2, 0x83, 0x57, 0xa1, 0xce, 0x91, 0x36, 0xda, 0x6d, 0xe5, 0x98, 0x0e, + 0xf8, 0x69, 0x51, 0x7e, 0xf8, 0x05, 0x5c, 0x50, 0xe8, 0x33, 0x99, 0xee, 0x35, 0x28, 0xf2, 0x02, + 0x8b, 0x38, 0x21, 0x16, 0xa2, 0xb3, 0x38, 0x8c, 0x21, 0x68, 0xf0, 0x6d, 0x98, 0x17, 0x3d, 0xa4, + 0xef, 0x24, 0xad, 0x3a, 0xb3, 0x0f, 0xde, 0x83, 0x85, 0x28, 0x59, 0x26, 0x47, 0xd8, 0x90, 0xa0, + 0x4f, 0x07, 0x6d, 0xe5, 0xc0, 0x89, 0x2f, 0x8a, 0x6a, 0xb0, 0x5c, 0xcc, 0x60, 0x81, 0x40, 0x92, + 0x45, 0x26, 0x81, 0xe6, 0xa5, 0xf9, 0xf7, 0x2c, 0x2f, 0x48, 0x2b, 0x3e, 0x05, 0xa4, 0x76, 0x66, + 0x5a, 0x94, 0x55, 0x28, 0x71, 0x83, 0xcb, 0xcc, 0x35, 0x79, 0x55, 0x24, 0x11, 0x15, 0x68, 0x8b, + 0x3c, 0x77, 0xcd, 0x4e, 0x9f, 0x04, 0x91, 0x95, 0xe6, 0x6b, 0x6a, 0x67, 0x26, 0x8d, 0xff, 0xa0, + 0x41, 0x75, 0xa3, 0x67, 0xba, 0x7d, 0x69, 0xfc, 0x77, 0xa1, 0xc8, 0x13, 0x41, 0x71, 0x59, 0xba, + 0x13, 0x65, 0xa3, 0xd2, 0xf2, 0xc6, 0x06, 0x4f, 0x1b, 0xc5, 0x2c, 0xba, 0x58, 0xa2, 0xae, 0xb7, + 0x15, 0xab, 0xf3, 0x6d, 0xa1, 0xd7, 0x61, 0xda, 0xa4, 0x53, 0x98, 0xff, 0xd6, 0xe2, 0x29, 0x38, + 0xe3, 0xc6, 0x0e, 0x6d, 0x4e, 0x85, 0xdf, 0x86, 0x8a, 0x82, 0x40, 0x6f, 0x16, 0x8f, 0x9b, 0xe2, + 0x60, 0xde, 0xd8, 0x3c, 0xda, 0x79, 0xc6, 0x2f, 0x1c, 0x35, 0x80, 0xad, 0x66, 0xd0, 0xce, 0xe1, + 0x8f, 0xc4, 0x2c, 0xe1, 0xe1, 0xaa, 0x3c, 0x5a, 0x9a, 0x3c, 0xb9, 0x57, 0x92, 0xe7, 0x25, 0xcc, + 0x0a, 0xf5, 0x33, 0xed, 0x81, 0x37, 0xa1, 0xc8, 0xf8, 0xc9, 0x2d, 0xb0, 0x98, 0x00, 0x2b, 0xbd, + 0x93, 0x13, 0xe2, 0x39, 0x98, 0x3d, 0xf4, 0x4d, 0x7f, 0xe8, 0xc9, 0x2d, 0xf0, 0x7b, 0x0d, 0x6a, + 0xb2, 0x27, 0x6b, 0x5d, 0x45, 0xde, 0x47, 0x79, 0xcc, 0x0b, 0x6e, 0xa3, 0x97, 0xa0, 0xd8, 0x3e, + 0x39, 0xb4, 0x3e, 0x95, 0xd5, 0x2b, 0xd1, 0xa2, 0xfd, 0x3d, 0x8e, 0xc3, 0xab, 0xb1, 0xa2, 0x45, + 0x2f, 0x3a, 0xae, 0xf9, 0xdc, 0xdf, 0xb1, 0xdb, 0xe4, 0x25, 0xcb, 0x27, 0x0a, 0x46, 0xd8, 0xc1, + 0xee, 0x26, 0xa2, 0x6a, 0xcb, 0xf2, 0x2f, 0xb5, 0x8a, 0x3b, 0x0f, 0x17, 0x36, 0x86, 0x7e, 0xb7, + 0x69, 0x9b, 0x27, 0x3d, 0x19, 0x04, 0xf0, 0x02, 0x20, 0xda, 0xb9, 0x65, 0x79, 0x6a, 0x6f, 0x13, + 0xe6, 0x69, 0x2f, 0xb1, 0x7d, 0xab, 0xa5, 0x44, 0x0c, 0x19, 0xb6, 0xb5, 0x58, 0xd8, 0x36, 0x3d, + 0xef, 0x85, 0xe3, 0xb6, 0x85, 0x6a, 0x41, 0x1b, 0x6f, 0x71, 0xe6, 0x4f, 0xbd, 0x48, 0x60, 0xfe, + 0xa6, 0x5c, 0x56, 0x42, 0x2e, 0x8f, 0x89, 0x3f, 0x81, 0x0b, 0x7e, 0x00, 0x17, 0x25, 0xa5, 0x28, + 0x58, 0x4c, 0x20, 0x3e, 0x80, 0x6b, 0x92, 0x78, 0xb3, 0x4b, 0xb3, 0xea, 0x27, 0x02, 0xf0, 0xdf, + 0x95, 0xf3, 0x11, 0x34, 0x02, 0x39, 0x59, 0xa6, 0xe5, 0xf4, 0x54, 0x01, 0x86, 0x9e, 0xd8, 0x33, + 0x65, 0x83, 0x7d, 0xd3, 0x3e, 0xd7, 0xe9, 0x05, 0x87, 0x20, 0xfd, 0xc6, 0x9b, 0xb0, 0x28, 0x79, + 0x88, 0x1c, 0x28, 0xca, 0x64, 0x4c, 0xa0, 0x24, 0x26, 0xc2, 0x60, 0x74, 0xea, 0x64, 0xb3, 0xab, + 0x94, 0x51, 0xd3, 0x32, 0x9e, 0x9a, 0xc2, 0xf3, 0x22, 0xdf, 0x11, 0x54, 0x30, 0x35, 0x68, 0x8b, + 0x6e, 0xca, 0x40, 0xed, 0x16, 0x0b, 0x41, 0xbb, 0xc7, 0x16, 0x62, 0x8c, 0xf5, 0xc7, 0xb0, 0x14, + 0x08, 0x41, 0xed, 0xf6, 0x84, 0xb8, 0x7d, 0xcb, 0xf3, 0x94, 0x1b, 0x77, 0x92, 0xe2, 0x77, 0xa0, + 0x30, 0x20, 0x22, 0xa6, 0x54, 0xd6, 0xd1, 0x2a, 0x7f, 0x5b, 0x59, 0x55, 0x26, 0xb3, 0x71, 0xdc, + 0x86, 0xeb, 0x92, 0x3b, 0xb7, 0x68, 0x22, 0xfb, 0xb8, 0x50, 0xf2, 0x36, 0xc6, 0xcd, 0x3a, 0x7e, + 0x1b, 0xcb, 0xf3, 0xb5, 0x97, 0xb7, 0x31, 0x7a, 0x56, 0xa8, 0xbe, 0x95, 0xe9, 0xac, 0xd8, 0xe5, + 0x36, 0x0d, 0x5c, 0x32, 0x13, 0xb3, 0x13, 0x58, 0x88, 0x7a, 0x72, 0xa6, 0x30, 0xb6, 0x00, 0xd3, + 0xbe, 0x73, 0x4a, 0x64, 0x10, 0xe3, 0x0d, 0x29, 0x70, 0xe0, 0xe6, 0x99, 0x04, 0x36, 0x43, 0x66, + 0x6c, 0x4b, 0x66, 0x95, 0x97, 0xae, 0xa6, 0xcc, 0x67, 0x78, 0x03, 0xef, 0xc3, 0xa5, 0x78, 0x98, + 0xc8, 0x24, 0xf2, 0x33, 0xbe, 0x81, 0x93, 0x22, 0x49, 0x26, 0xbe, 0x1f, 0x84, 0xc1, 0x40, 0x09, + 0x28, 0x99, 0x58, 0x1a, 0xa0, 0x27, 0xc5, 0x97, 0xff, 0xc4, 0x7e, 0x0d, 0xc2, 0x4d, 0x26, 0x66, + 0x5e, 0xc8, 0x2c, 0xfb, 0xf2, 0x87, 0x31, 0x22, 0x3f, 0x31, 0x46, 0x08, 0x27, 0x09, 0xa3, 0xd8, + 0xb7, 0xb0, 0xe9, 0x04, 0x46, 0x18, 0x40, 0xb3, 0x62, 0xd0, 0x33, 0x24, 0xc0, 0x60, 0x0d, 0xb9, + 0xb1, 0xd5, 0xb0, 0x9b, 0x69, 0x31, 0x3e, 0x0c, 0x63, 0xe7, 0x58, 0x64, 0xce, 0xc4, 0xf8, 0x23, + 0x58, 0x4e, 0x0f, 0xca, 0x59, 0x38, 0xdf, 0xc7, 0x50, 0x0e, 0x12, 0x4a, 0xe5, 0x2d, 0xb5, 0x02, + 0xa5, 0xfd, 0x83, 0xc3, 0x27, 0x1b, 0x9b, 0xcd, 0xba, 0xb6, 0xfe, 0x8f, 0x3c, 0xe4, 0x76, 0x9f, + 0xa1, 0xff, 0x87, 0x69, 0xfe, 0xd2, 0x32, 0xe1, 0x21, 0x4a, 0x9f, 0xf4, 0x66, 0x83, 0xaf, 0x7e, + 0xf6, 0xc7, 0xbf, 0x7c, 0x91, 0xbb, 0x84, 0x2f, 0xac, 0x8d, 0xde, 0x32, 0x7b, 0x83, 0xae, 0xb9, + 0x76, 0x3a, 0x5a, 0x63, 0x67, 0xc2, 0x43, 0xed, 0x3e, 0x7a, 0x06, 0xf9, 0x27, 0x43, 0x1f, 0xa5, + 0xbe, 0x52, 0xe9, 0xe9, 0x6f, 0x39, 0x58, 0x67, 0x9c, 0x17, 0xf0, 0x9c, 0xca, 0x79, 0x30, 0xf4, + 0x29, 0xdf, 0x11, 0x54, 0x94, 0xe7, 0x18, 0x74, 0xee, 0xfb, 0x95, 0x7e, 0xfe, 0x53, 0x0f, 0xc6, + 0x0c, 0xef, 0x2a, 0xbe, 0xac, 0xe2, 0xf1, 0x57, 0x23, 0x55, 0x9f, 0xa3, 0x97, 0x76, 0x5c, 0x9f, + 0xf0, 0x81, 0x21, 0xae, 0x8f, 0x52, 0xd4, 0x4f, 0xd6, 0xc7, 0x7f, 0x69, 0x53, 0xbe, 0x8e, 0x78, + 0x42, 0x6a, 0xf9, 0xe8, 0x7a, 0xc2, 0x8b, 0x84, 0x5a, 0x7b, 0xd7, 0x97, 0xd3, 0x09, 0x04, 0xd2, + 0x0d, 0x86, 0x74, 0x05, 0x5f, 0x52, 0x91, 0x5a, 0x01, 0xdd, 0x43, 0xed, 0xfe, 0x7a, 0x17, 0xa6, + 0x59, 0xc5, 0x10, 0x1d, 0xcb, 0x0f, 0x3d, 0xa1, 0xd6, 0x99, 0xb2, 0x03, 0x22, 0xb5, 0x46, 0xbc, + 0xc8, 0xd0, 0xe6, 0x71, 0x2d, 0x40, 0x63, 0x45, 0xc3, 0x87, 0xda, 0xfd, 0x15, 0xed, 0x0d, 0x6d, + 0xfd, 0x07, 0x05, 0x98, 0x66, 0x95, 0x1a, 0x34, 0x00, 0x08, 0x6b, 0x70, 0x71, 0x3d, 0xc7, 0xaa, + 0x7a, 0x71, 0x3d, 0xc7, 0xcb, 0x77, 0xf8, 0x3a, 0x43, 0x5e, 0xc4, 0x0b, 0x01, 0x32, 0x7b, 0xf6, + 0x5e, 0x63, 0x35, 0x19, 0x6a, 0xd6, 0x17, 0x50, 0x51, 0x6a, 0x69, 0x28, 0x89, 0x63, 0xa4, 0x18, + 0x17, 0xdf, 0x26, 0x09, 0x85, 0x38, 0x7c, 0x93, 0x81, 0x5e, 0xc3, 0x0d, 0xd5, 0xb8, 0x1c, 0xd7, + 0x65, 0x94, 0x14, 0xf8, 0x87, 0x1a, 0xd4, 0xa2, 0xf5, 0x34, 0x74, 0x33, 0x81, 0x75, 0xbc, 0x2c, + 0xa7, 0xdf, 0x9a, 0x4c, 0x94, 0x2a, 0x02, 0xc7, 0x3f, 0x25, 0x64, 0x60, 0x52, 0x4a, 0x61, 0x7b, + 0xf4, 0x23, 0x0d, 0xe6, 0x62, 0x55, 0x32, 0x94, 0x04, 0x31, 0x56, 0x83, 0xd3, 0x6f, 0x9f, 0x43, + 0x25, 0x24, 0xb9, 0xcb, 0x24, 0xb9, 0x81, 0xaf, 0x8e, 0x1b, 0xc3, 0xb7, 0xfa, 0xc4, 0x77, 0x84, + 0x34, 0xeb, 0xff, 0xcc, 0x43, 0x69, 0x93, 0xff, 0x44, 0x07, 0xf9, 0x50, 0x0e, 0x2a, 0x4f, 0x68, + 0x29, 0xa9, 0x2a, 0x11, 0xa6, 0xec, 0xfa, 0xf5, 0xd4, 0x71, 0x21, 0xc2, 0x1d, 0x26, 0xc2, 0x32, + 0xbe, 0x12, 0x88, 0x20, 0x7e, 0x0a, 0xb4, 0xc6, 0x2f, 0xdf, 0x6b, 0x66, 0xbb, 0x4d, 0x97, 0xe4, + 0xfb, 0x1a, 0x54, 0xd5, 0x82, 0x12, 0xba, 0x91, 0x58, 0x0f, 0x51, 0x6b, 0x52, 0x3a, 0x9e, 0x44, + 0x22, 0xf0, 0xef, 0x31, 0xfc, 0x9b, 0x78, 0x29, 0x0d, 0xdf, 0x65, 0xf4, 0x51, 0x11, 0x78, 0x09, + 0x29, 0x59, 0x84, 0x48, 0x85, 0x2a, 0x59, 0x84, 0x68, 0x05, 0xea, 0x7c, 0x11, 0x86, 0x8c, 0x9e, + 0x8a, 0xf0, 0x12, 0x20, 0xac, 0x30, 0xa1, 0x44, 0xe3, 0x2a, 0x97, 0x98, 0xb8, 0x0f, 0x8e, 0x17, + 0xa7, 0x12, 0x76, 0x40, 0x0c, 0xbb, 0x67, 0x79, 0xd4, 0x17, 0xd7, 0x7f, 0x5b, 0x80, 0xca, 0xfb, + 0xa6, 0x65, 0xfb, 0xc4, 0x36, 0xed, 0x16, 0x41, 0x1d, 0x98, 0x66, 0xa7, 0x54, 0x3c, 0xf0, 0xa8, + 0x65, 0x9f, 0x78, 0xe0, 0x89, 0xd4, 0x44, 0xf0, 0x6d, 0x06, 0x7d, 0x1d, 0xeb, 0x01, 0x74, 0x3f, + 0xe4, 0xbf, 0xc6, 0xea, 0x19, 0x54, 0xe5, 0x53, 0x28, 0xf2, 0xfa, 0x05, 0x8a, 0x71, 0x8b, 0xd4, + 0x39, 0xf4, 0xab, 0xc9, 0x83, 0xa9, 0xbb, 0x4c, 0xc5, 0xf2, 0x18, 0x31, 0x05, 0xfb, 0x0e, 0x40, + 0x58, 0x30, 0x8b, 0xdb, 0x77, 0xac, 0xbe, 0xa6, 0x2f, 0xa7, 0x13, 0x08, 0xe0, 0xfb, 0x0c, 0xf8, + 0x16, 0xbe, 0x9e, 0x08, 0xdc, 0x0e, 0x26, 0x50, 0xf0, 0x16, 0x14, 0xb6, 0x4d, 0xaf, 0x8b, 0x62, + 0x87, 0x90, 0xf2, 0x4a, 0xaa, 0xeb, 0x49, 0x43, 0x02, 0xea, 0x16, 0x83, 0x5a, 0xc2, 0x8b, 0x89, + 0x50, 0x5d, 0xd3, 0xa3, 0x31, 0x1d, 0x0d, 0x61, 0x46, 0xbe, 0x7c, 0xa2, 0x6b, 0x31, 0x9b, 0x45, + 0x5f, 0x49, 0xf5, 0xa5, 0xb4, 0x61, 0x01, 0xb8, 0xc2, 0x00, 0x31, 0xbe, 0x96, 0x6c, 0x54, 0x41, + 0xfe, 0x50, 0xbb, 0xff, 0x86, 0xb6, 0xfe, 0x93, 0x3a, 0x14, 0x68, 0xbe, 0x44, 0x4f, 0x91, 0xf0, + 0x9a, 0x19, 0xb7, 0xf0, 0x58, 0x71, 0x27, 0x6e, 0xe1, 0xf1, 0x1b, 0x6a, 0xc2, 0x29, 0xc2, 0x7e, + 0xa8, 0x48, 0x18, 0x15, 0xd5, 0xd8, 0x87, 0x8a, 0x72, 0x19, 0x45, 0x09, 0x1c, 0xa3, 0xa5, 0xa3, + 0xf8, 0x29, 0x92, 0x70, 0x93, 0xc5, 0xcb, 0x0c, 0x54, 0xc7, 0x17, 0xa3, 0xa0, 0x6d, 0x4e, 0x46, + 0x51, 0xbf, 0x0b, 0x55, 0xf5, 0xd6, 0x8a, 0x12, 0x98, 0xc6, 0x6a, 0x53, 0xf1, 0x58, 0x91, 0x74, + 0xe9, 0x4d, 0x70, 0x9a, 0xe0, 0x67, 0x99, 0x92, 0x96, 0xa2, 0x7f, 0x02, 0x25, 0x71, 0x97, 0x4d, + 0xd2, 0x37, 0x5a, 0xcd, 0x4a, 0xd2, 0x37, 0x76, 0x11, 0x4e, 0x48, 0x49, 0x18, 0x2c, 0xcd, 0xd9, + 0x65, 0x80, 0x16, 0x90, 0x8f, 0x89, 0x9f, 0x06, 0x19, 0xd6, 0x67, 0xd2, 0x20, 0x95, 0xfb, 0xd2, + 0x44, 0xc8, 0x0e, 0xf1, 0xc5, 0x5e, 0x96, 0x97, 0x11, 0x94, 0xc2, 0x51, 0x8d, 0x86, 0x78, 0x12, + 0x49, 0x6a, 0x16, 0x19, 0xa2, 0x8a, 0x50, 0x88, 0xbe, 0x07, 0x10, 0x5e, 0xbc, 0xe3, 0x89, 0x41, + 0x62, 0xf5, 0x2e, 0x9e, 0x18, 0x24, 0xdf, 0xdd, 0x13, 0x3c, 0x38, 0x04, 0xe7, 0x99, 0x2c, 0x85, + 0xff, 0x99, 0x06, 0x68, 0xfc, 0xa2, 0x8e, 0x1e, 0x24, 0x43, 0x24, 0x16, 0x06, 0xf5, 0xd7, 0x5e, + 0x8d, 0x38, 0x35, 0x7a, 0x86, 0x72, 0xb5, 0xd8, 0x94, 0xc1, 0x0b, 0x2a, 0xd9, 0xe7, 0x1a, 0xcc, + 0x46, 0xae, 0xfa, 0xe8, 0x4e, 0xca, 0x3a, 0xc7, 0x8a, 0x8b, 0xfa, 0xdd, 0x73, 0xe9, 0x52, 0x73, + 0x27, 0x65, 0x57, 0xc8, 0xbc, 0xf1, 0xc7, 0x1a, 0xd4, 0xa2, 0xf5, 0x01, 0x94, 0x02, 0x30, 0x56, + 0xa1, 0xd4, 0x57, 0xce, 0x27, 0x7c, 0x85, 0xd5, 0x0a, 0x53, 0xc9, 0x4f, 0xa0, 0x24, 0xca, 0x0a, + 0x49, 0x6e, 0x11, 0x2d, 0x70, 0x26, 0xb9, 0x45, 0xac, 0x26, 0x91, 0xe6, 0x16, 0xf4, 0x86, 0xae, + 0x78, 0xa2, 0x28, 0x3e, 0xa4, 0x41, 0x4e, 0xf6, 0xc4, 0x58, 0xe5, 0x62, 0x22, 0x64, 0xe8, 0x89, + 0xb2, 0xf4, 0x80, 0x52, 0x38, 0x9e, 0xe3, 0x89, 0xf1, 0xca, 0x45, 0x9a, 0x27, 0x32, 0x54, 0xc5, + 0x13, 0xc3, 0x4a, 0x41, 0x92, 0x27, 0x8e, 0x95, 0x6f, 0x93, 0x3c, 0x71, 0xbc, 0xd8, 0x90, 0xb6, + 0xb6, 0x0c, 0x3c, 0xe2, 0x89, 0xf3, 0x09, 0x95, 0x05, 0xf4, 0x5a, 0x8a, 0x4d, 0x13, 0x4b, 0xc3, + 0xfa, 0xeb, 0xaf, 0x48, 0x3d, 0xd9, 0x03, 0xf8, 0x6a, 0x48, 0x0f, 0xf8, 0xa5, 0x06, 0x0b, 0x49, + 0xa5, 0x09, 0x94, 0x02, 0x96, 0x52, 0x57, 0xd6, 0x57, 0x5f, 0x95, 0xfc, 0x15, 0xec, 0x16, 0xf8, + 0xc4, 0xa3, 0xfa, 0xef, 0xbe, 0x5e, 0xd2, 0xbe, 0xfa, 0x7a, 0x49, 0xfb, 0xd3, 0xd7, 0x4b, 0xda, + 0xcf, 0xff, 0xbc, 0x34, 0x75, 0x52, 0x64, 0xff, 0x5b, 0xe0, 0xad, 0x7f, 0x05, 0x00, 0x00, 0xff, + 0xff, 0xb2, 0xe7, 0xb7, 0xba, 0xb4, 0x30, 0x00, 0x00, } diff --git a/etcdserver/etcdserverpb/rpc.pb.gw.go b/etcdserver/etcdserverpb/rpc.pb.gw.go index a2efbcd98..473ad582e 100644 --- a/etcdserver/etcdserverpb/rpc.pb.gw.go +++ b/etcdserver/etcdserverpb/rpc.pb.gw.go @@ -222,6 +222,19 @@ func request_Lease_LeaseKeepAlive_0(ctx context.Context, marshaler runtime.Marsh return stream, metadata, nil } +func request_Lease_LeaseTimeToLive_0(ctx context.Context, marshaler runtime.Marshaler, client LeaseClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq LeaseTimeToLiveRequest + var metadata runtime.ServerMetadata + + if err := marshaler.NewDecoder(req.Body).Decode(&protoReq); err != nil { + return nil, metadata, grpc.Errorf(codes.InvalidArgument, "%v", err) + } + + msg, err := client.LeaseTimeToLive(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) + return msg, metadata, err + +} + func request_Cluster_MemberAdd_0(ctx context.Context, marshaler runtime.Marshaler, client ClusterClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { var protoReq MemberAddRequest var metadata runtime.ServerMetadata @@ -935,6 +948,34 @@ func RegisterLeaseHandler(ctx context.Context, mux *runtime.ServeMux, conn *grpc }) + mux.Handle("POST", pattern_Lease_LeaseTimeToLive_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + ctx, cancel := context.WithCancel(ctx) + defer cancel() + if cn, ok := w.(http.CloseNotifier); ok { + go func(done <-chan struct{}, closed <-chan bool) { + select { + case <-done: + case <-closed: + cancel() + } + }(ctx.Done(), cn.CloseNotify()) + } + inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) + rctx, err := runtime.AnnotateContext(ctx, req) + if err != nil { + runtime.HTTPError(ctx, outboundMarshaler, w, req, err) + } + resp, md, err := request_Lease_LeaseTimeToLive_0(rctx, inboundMarshaler, client, req, pathParams) + ctx = runtime.NewServerMetadataContext(ctx, md) + if err != nil { + runtime.HTTPError(ctx, outboundMarshaler, w, req, err) + return + } + + forward_Lease_LeaseTimeToLive_0(ctx, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + return nil } @@ -944,6 +985,8 @@ var ( pattern_Lease_LeaseRevoke_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3}, []string{"v3alpha", "kv", "lease", "revoke"}, "")) pattern_Lease_LeaseKeepAlive_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2}, []string{"v3alpha", "lease", "keepalive"}, "")) + + pattern_Lease_LeaseTimeToLive_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3}, []string{"v3alpha", "kv", "lease", "timetolive"}, "")) ) var ( @@ -952,6 +995,8 @@ var ( forward_Lease_LeaseRevoke_0 = runtime.ForwardResponseMessage forward_Lease_LeaseKeepAlive_0 = runtime.ForwardResponseStream + + forward_Lease_LeaseTimeToLive_0 = runtime.ForwardResponseMessage ) // RegisterClusterHandlerFromEndpoint is same as RegisterClusterHandler but diff --git a/etcdserver/etcdserverpb/rpc.proto b/etcdserver/etcdserverpb/rpc.proto index 5a0bb5d7b..cedf6df6e 100644 --- a/etcdserver/etcdserverpb/rpc.proto +++ b/etcdserver/etcdserverpb/rpc.proto @@ -104,8 +104,15 @@ service Lease { }; } + // LeaseTimeToLive retrieves lease information. + rpc LeaseTimeToLive(LeaseTimeToLiveRequest) returns (LeaseTimeToLiveResponse) { + option (google.api.http) = { + post: "/v3alpha/kv/lease/timetolive" + body: "*" + }; + } + // TODO(xiangli) List all existing Leases? - // TODO(xiangli) Get details information (expirations, leased keys, etc.) of a lease? } service Cluster { @@ -658,6 +665,25 @@ message LeaseKeepAliveResponse { int64 TTL = 3; } +message LeaseTimeToLiveRequest { + // ID is the lease ID for the lease. + int64 ID = 1; + // keys is true to query all the keys attached to this lease. + bool keys = 2; +} + +message LeaseTimeToLiveResponse { + ResponseHeader header = 1; + // ID is the lease ID from the keep alive request. + int64 ID = 2; + // TTL is the remaining TTL in seconds for the lease; the lease will expire in under TTL+1 seconds. + int64 TTL = 3; + // GrantedTTL is the initial granted time in seconds upon lease creation/renewal. + int64 grantedTTL = 4; + // Keys is the list of keys attached to this lease. + repeated bytes keys = 5; +} + message Member { // ID is the member ID for this member. uint64 ID = 1; diff --git a/etcdserver/v3_server.go b/etcdserver/v3_server.go index 3e041d239..395f75deb 100644 --- a/etcdserver/v3_server.go +++ b/etcdserver/v3_server.go @@ -21,8 +21,10 @@ import ( "github.com/coreos/etcd/auth" pb "github.com/coreos/etcd/etcdserver/etcdserverpb" + "github.com/coreos/etcd/etcdserver/membership" "github.com/coreos/etcd/lease" "github.com/coreos/etcd/lease/leasehttp" + "github.com/coreos/etcd/lease/leasepb" "github.com/coreos/etcd/mvcc" "golang.org/x/net/context" "google.golang.org/grpc/metadata" @@ -59,6 +61,9 @@ type Lessor interface { // LeaseRenew renews the lease with given ID. The renewed TTL is returned. Or an error // is returned. LeaseRenew(id lease.LeaseID) (int64, error) + + // LeaseTimeToLive retrieves lease information. + LeaseTimeToLive(ctx context.Context, r *pb.LeaseTimeToLiveRequest) (*pb.LeaseTimeToLiveResponse, error) } type Authenticator interface { @@ -219,7 +224,7 @@ func (s *EtcdServer) LeaseRevoke(ctx context.Context, r *pb.LeaseRevokeRequest) func (s *EtcdServer) LeaseRenew(id lease.LeaseID) (int64, error) { ttl, err := s.lessor.Renew(id) - if err == nil { + if err == nil { // already requested to primary lessor(leader) return ttl, nil } if err != lease.ErrNotPrimary { @@ -227,6 +232,61 @@ func (s *EtcdServer) LeaseRenew(id lease.LeaseID) (int64, error) { } // renewals don't go through raft; forward to leader manually + leader, err := s.waitLeader() + if err != nil { + return -1, err + } + + for _, url := range leader.PeerURLs { + lurl := url + leasehttp.LeasePrefix + ttl, err = leasehttp.RenewHTTP(id, lurl, s.peerRt, s.Cfg.peerDialTimeout()) + if err == nil { + break + } + } + return ttl, err +} + +func (s *EtcdServer) LeaseTimeToLive(ctx context.Context, r *pb.LeaseTimeToLiveRequest) (*pb.LeaseTimeToLiveResponse, error) { + if s.Leader() == s.ID() { + // primary; timetolive directly from leader + le := s.lessor.Lookup(lease.LeaseID(r.ID)) + if le == nil { + return nil, lease.ErrLeaseNotFound + } + // TODO: fill out ResponseHeader + resp := &pb.LeaseTimeToLiveResponse{Header: &pb.ResponseHeader{}, ID: r.ID, TTL: int64(le.Remaining().Seconds()), GrantedTTL: le.TTL} + if r.Keys { + ks := le.Keys() + kbs := make([][]byte, len(ks)) + for i := range ks { + kbs[i] = []byte(ks[i]) + } + resp.Keys = kbs + } + return resp, nil + } + + // manually request to leader + leader, err := s.waitLeader() + if err != nil { + return nil, err + } + + var lresp *pb.LeaseTimeToLiveResponse + for _, url := range leader.PeerURLs { + lurl := url + leasehttp.LeaseInternalPrefix + var iresp *leasepb.LeaseInternalResponse + iresp, err = leasehttp.TimeToLiveHTTP(ctx, lease.LeaseID(r.ID), r.Keys, lurl, s.peerRt) + if err == nil { + lresp = iresp.LeaseTimeToLiveResponse + break + } + } + return lresp, nil +} + +func (s *EtcdServer) waitLeader() (*membership.Member, error) { leader := s.cluster.Member(s.Leader()) for i := 0; i < 5 && leader == nil; i++ { // wait an election @@ -235,21 +295,13 @@ func (s *EtcdServer) LeaseRenew(id lease.LeaseID) (int64, error) { case <-time.After(dur): leader = s.cluster.Member(s.Leader()) case <-s.done: - return -1, ErrStopped + return nil, ErrStopped } } if leader == nil || len(leader.PeerURLs) == 0 { - return -1, ErrNoLeader + return nil, ErrNoLeader } - - for _, url := range leader.PeerURLs { - lurl := url + "/leases" - ttl, err = leasehttp.RenewHTTP(id, lurl, s.peerRt, s.Cfg.peerDialTimeout()) - if err == nil { - break - } - } - return ttl, err + return leader, nil } func (s *EtcdServer) Alarm(ctx context.Context, r *pb.AlarmRequest) (*pb.AlarmResponse, error) { diff --git a/lease/leasehttp/http.go b/lease/leasehttp/http.go index cf95595b6..c82b1dafe 100644 --- a/lease/leasehttp/http.go +++ b/lease/leasehttp/http.go @@ -23,6 +23,14 @@ import ( pb "github.com/coreos/etcd/etcdserver/etcdserverpb" "github.com/coreos/etcd/lease" + "github.com/coreos/etcd/lease/leasepb" + "github.com/coreos/etcd/pkg/httputil" + "golang.org/x/net/context" +) + +var ( + LeasePrefix = "/leases" + LeaseInternalPrefix = "/leases/internal" ) // NewHandler returns an http Handler for lease renewals @@ -44,28 +52,70 @@ func (h *leaseHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) { return } - lreq := pb.LeaseKeepAliveRequest{} - if err := lreq.Unmarshal(b); err != nil { - http.Error(w, "error unmarshalling request", http.StatusBadRequest) - return - } + var v []byte + switch r.URL.Path { + case LeasePrefix: + lreq := pb.LeaseKeepAliveRequest{} + if err := lreq.Unmarshal(b); err != nil { + http.Error(w, "error unmarshalling request", http.StatusBadRequest) + return + } + ttl, err := h.l.Renew(lease.LeaseID(lreq.ID)) + if err != nil { + if err == lease.ErrLeaseNotFound { + http.Error(w, err.Error(), http.StatusNotFound) + return + } - ttl, err := h.l.Renew(lease.LeaseID(lreq.ID)) - if err != nil { - if err == lease.ErrLeaseNotFound { - http.Error(w, err.Error(), http.StatusNotFound) + http.Error(w, err.Error(), http.StatusBadRequest) + return + } + // TODO: fill out ResponseHeader + resp := &pb.LeaseKeepAliveResponse{ID: lreq.ID, TTL: ttl} + v, err = resp.Marshal() + if err != nil { + http.Error(w, err.Error(), http.StatusInternalServerError) return } - http.Error(w, err.Error(), http.StatusBadRequest) - return - } + case LeaseInternalPrefix: + lreq := leasepb.LeaseInternalRequest{} + if err := lreq.Unmarshal(b); err != nil { + http.Error(w, "error unmarshalling request", http.StatusBadRequest) + return + } - // TODO: fill out ResponseHeader - resp := &pb.LeaseKeepAliveResponse{ID: lreq.ID, TTL: ttl} - v, err := resp.Marshal() - if err != nil { - http.Error(w, err.Error(), http.StatusInternalServerError) + l := h.l.Lookup(lease.LeaseID(lreq.LeaseTimeToLiveRequest.ID)) + if l == nil { + http.Error(w, lease.ErrLeaseNotFound.Error(), http.StatusNotFound) + return + } + // TODO: fill out ResponseHeader + resp := &leasepb.LeaseInternalResponse{ + LeaseTimeToLiveResponse: &pb.LeaseTimeToLiveResponse{ + Header: &pb.ResponseHeader{}, + ID: lreq.LeaseTimeToLiveRequest.ID, + TTL: int64(l.Remaining().Seconds()), + GrantedTTL: l.TTL, + }, + } + if lreq.LeaseTimeToLiveRequest.Keys { + ks := l.Keys() + kbs := make([][]byte, len(ks)) + for i := range ks { + kbs[i] = []byte(ks[i]) + } + resp.LeaseTimeToLiveResponse.Keys = kbs + } + + v, err = resp.Marshal() + if err != nil { + http.Error(w, err.Error(), http.StatusInternalServerError) + return + } + + default: + http.Error(w, fmt.Sprintf("unknown request path %q", r.URL.Path), http.StatusBadRequest) return } @@ -111,3 +161,65 @@ func RenewHTTP(id lease.LeaseID, url string, rt http.RoundTripper, timeout time. } return lresp.TTL, nil } + +// TimeToLiveHTTP retrieves lease information of the given lease ID. +func TimeToLiveHTTP(ctx context.Context, id lease.LeaseID, keys bool, url string, rt http.RoundTripper) (*leasepb.LeaseInternalResponse, error) { + // will post lreq protobuf to leader + lreq, err := (&leasepb.LeaseInternalRequest{&pb.LeaseTimeToLiveRequest{ID: int64(id), Keys: keys}}).Marshal() + if err != nil { + return nil, err + } + + req, err := http.NewRequest("POST", url, bytes.NewReader(lreq)) + if err != nil { + return nil, err + } + req.Header.Set("Content-Type", "application/protobuf") + + cancel := httputil.RequestCanceler(req) + + cc := &http.Client{Transport: rt} + var b []byte + errc := make(chan error) + go func() { + // TODO detect if leader failed and retry? + resp, err := cc.Do(req) + if err != nil { + errc <- err + return + } + b, err = ioutil.ReadAll(resp.Body) + resp.Body.Close() + if err != nil { + errc <- err + return + } + if resp.StatusCode == http.StatusNotFound { + errc <- lease.ErrLeaseNotFound + return + } + if resp.StatusCode != http.StatusOK { + errc <- fmt.Errorf("lease: unknown error(%s)", string(b)) + return + } + errc <- nil + }() + select { + case derr := <-errc: + if derr != nil { + return nil, derr + } + case <-ctx.Done(): + cancel() + return nil, ctx.Err() + } + + lresp := &leasepb.LeaseInternalResponse{} + if err := lresp.Unmarshal(b); err != nil { + return nil, fmt.Errorf(`lease: %v. data = "%s"`, err, string(b)) + } + if lresp.LeaseTimeToLiveResponse.ID != int64(id) { + return nil, fmt.Errorf("lease: renew id mismatch") + } + return lresp, nil +} diff --git a/lease/leasepb/lease.pb.go b/lease/leasepb/lease.pb.go index 62115a3c9..59e2f8663 100644 --- a/lease/leasepb/lease.pb.go +++ b/lease/leasepb/lease.pb.go @@ -10,6 +10,8 @@ It has these top-level messages: Lease + LeaseInternalRequest + LeaseInternalResponse */ package leasepb @@ -19,9 +21,11 @@ import ( proto "github.com/golang/protobuf/proto" math "math" + + io "io" ) -import io "io" +import etcdserverpb "github.com/coreos/etcd/etcdserver/etcdserverpb" // Reference imports to suppress errors if they are not otherwise used. var _ = proto.Marshal @@ -42,8 +46,28 @@ func (m *Lease) String() string { return proto.CompactTextString(m) } func (*Lease) ProtoMessage() {} func (*Lease) Descriptor() ([]byte, []int) { return fileDescriptorLease, []int{0} } +type LeaseInternalRequest struct { + LeaseTimeToLiveRequest *etcdserverpb.LeaseTimeToLiveRequest `protobuf:"bytes,1,opt,name=LeaseTimeToLiveRequest,json=leaseTimeToLiveRequest" json:"LeaseTimeToLiveRequest,omitempty"` +} + +func (m *LeaseInternalRequest) Reset() { *m = LeaseInternalRequest{} } +func (m *LeaseInternalRequest) String() string { return proto.CompactTextString(m) } +func (*LeaseInternalRequest) ProtoMessage() {} +func (*LeaseInternalRequest) Descriptor() ([]byte, []int) { return fileDescriptorLease, []int{1} } + +type LeaseInternalResponse struct { + LeaseTimeToLiveResponse *etcdserverpb.LeaseTimeToLiveResponse `protobuf:"bytes,1,opt,name=LeaseTimeToLiveResponse,json=leaseTimeToLiveResponse" json:"LeaseTimeToLiveResponse,omitempty"` +} + +func (m *LeaseInternalResponse) Reset() { *m = LeaseInternalResponse{} } +func (m *LeaseInternalResponse) String() string { return proto.CompactTextString(m) } +func (*LeaseInternalResponse) ProtoMessage() {} +func (*LeaseInternalResponse) Descriptor() ([]byte, []int) { return fileDescriptorLease, []int{2} } + func init() { proto.RegisterType((*Lease)(nil), "leasepb.Lease") + proto.RegisterType((*LeaseInternalRequest)(nil), "leasepb.LeaseInternalRequest") + proto.RegisterType((*LeaseInternalResponse)(nil), "leasepb.LeaseInternalResponse") } func (m *Lease) Marshal() (data []byte, err error) { size := m.Size() @@ -73,6 +97,62 @@ func (m *Lease) MarshalTo(data []byte) (int, error) { return i, nil } +func (m *LeaseInternalRequest) Marshal() (data []byte, err error) { + size := m.Size() + data = make([]byte, size) + n, err := m.MarshalTo(data) + if err != nil { + return nil, err + } + return data[:n], nil +} + +func (m *LeaseInternalRequest) MarshalTo(data []byte) (int, error) { + var i int + _ = i + var l int + _ = l + if m.LeaseTimeToLiveRequest != nil { + data[i] = 0xa + i++ + i = encodeVarintLease(data, i, uint64(m.LeaseTimeToLiveRequest.Size())) + n1, err := m.LeaseTimeToLiveRequest.MarshalTo(data[i:]) + if err != nil { + return 0, err + } + i += n1 + } + return i, nil +} + +func (m *LeaseInternalResponse) Marshal() (data []byte, err error) { + size := m.Size() + data = make([]byte, size) + n, err := m.MarshalTo(data) + if err != nil { + return nil, err + } + return data[:n], nil +} + +func (m *LeaseInternalResponse) MarshalTo(data []byte) (int, error) { + var i int + _ = i + var l int + _ = l + if m.LeaseTimeToLiveResponse != nil { + data[i] = 0xa + i++ + i = encodeVarintLease(data, i, uint64(m.LeaseTimeToLiveResponse.Size())) + n2, err := m.LeaseTimeToLiveResponse.MarshalTo(data[i:]) + if err != nil { + return 0, err + } + i += n2 + } + return i, nil +} + func encodeFixed64Lease(data []byte, offset int, v uint64) int { data[offset] = uint8(v) data[offset+1] = uint8(v >> 8) @@ -112,6 +192,26 @@ func (m *Lease) Size() (n int) { return n } +func (m *LeaseInternalRequest) Size() (n int) { + var l int + _ = l + if m.LeaseTimeToLiveRequest != nil { + l = m.LeaseTimeToLiveRequest.Size() + n += 1 + l + sovLease(uint64(l)) + } + return n +} + +func (m *LeaseInternalResponse) Size() (n int) { + var l int + _ = l + if m.LeaseTimeToLiveResponse != nil { + l = m.LeaseTimeToLiveResponse.Size() + n += 1 + l + sovLease(uint64(l)) + } + return n +} + func sovLease(x uint64) (n int) { for { n++ @@ -213,6 +313,172 @@ func (m *Lease) Unmarshal(data []byte) error { } return nil } +func (m *LeaseInternalRequest) Unmarshal(data []byte) error { + l := len(data) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowLease + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := data[iNdEx] + iNdEx++ + wire |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: LeaseInternalRequest: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: LeaseInternalRequest: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field LeaseTimeToLiveRequest", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowLease + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := data[iNdEx] + iNdEx++ + msglen |= (int(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthLease + } + postIndex := iNdEx + msglen + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.LeaseTimeToLiveRequest == nil { + m.LeaseTimeToLiveRequest = &etcdserverpb.LeaseTimeToLiveRequest{} + } + if err := m.LeaseTimeToLiveRequest.Unmarshal(data[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipLease(data[iNdEx:]) + if err != nil { + return err + } + if skippy < 0 { + return ErrInvalidLengthLease + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *LeaseInternalResponse) Unmarshal(data []byte) error { + l := len(data) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowLease + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := data[iNdEx] + iNdEx++ + wire |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: LeaseInternalResponse: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: LeaseInternalResponse: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field LeaseTimeToLiveResponse", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowLease + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := data[iNdEx] + iNdEx++ + msglen |= (int(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthLease + } + postIndex := iNdEx + msglen + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.LeaseTimeToLiveResponse == nil { + m.LeaseTimeToLiveResponse = &etcdserverpb.LeaseTimeToLiveResponse{} + } + if err := m.LeaseTimeToLiveResponse.Unmarshal(data[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipLease(data[iNdEx:]) + if err != nil { + return err + } + if skippy < 0 { + return ErrInvalidLengthLease + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} func skipLease(data []byte) (n int, err error) { l := len(data) iNdEx := 0 @@ -319,13 +585,20 @@ var ( ) var fileDescriptorLease = []byte{ - // 126 bytes of a gzipped FileDescriptorProto + // 239 bytes of a gzipped FileDescriptorProto 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0xe2, 0xe2, 0xce, 0x49, 0x4d, 0x2c, 0x4e, 0xd5, 0x2b, 0x28, 0xca, 0x2f, 0xc9, 0x17, 0x62, 0x07, 0x73, 0x0a, 0x92, 0xa4, 0x44, 0xd2, - 0xf3, 0xd3, 0xf3, 0xc1, 0x62, 0xfa, 0x20, 0x16, 0x44, 0x5a, 0x49, 0x93, 0x8b, 0xd5, 0x07, 0xa4, - 0x40, 0x88, 0x8f, 0x8b, 0xc9, 0xd3, 0x45, 0x82, 0x51, 0x81, 0x51, 0x83, 0x39, 0x88, 0x29, 0xd3, - 0x45, 0x48, 0x80, 0x8b, 0x39, 0x24, 0xc4, 0x47, 0x82, 0x09, 0x2c, 0xc0, 0x5c, 0x12, 0xe2, 0xe3, - 0x24, 0x71, 0xe2, 0xa1, 0x1c, 0xc3, 0x85, 0x87, 0x72, 0x0c, 0x27, 0x1e, 0xc9, 0x31, 0x5e, 0x78, - 0x24, 0xc7, 0xf8, 0xe0, 0x91, 0x1c, 0xe3, 0x8c, 0xc7, 0x72, 0x0c, 0x49, 0x6c, 0x60, 0xb3, 0x8c, - 0x01, 0x01, 0x00, 0x00, 0xff, 0xff, 0x0d, 0xa0, 0x42, 0x1a, 0x79, 0x00, 0x00, 0x00, + 0xf3, 0xd3, 0xf3, 0xc1, 0x62, 0xfa, 0x20, 0x16, 0x44, 0x5a, 0x4a, 0x2d, 0xb5, 0x24, 0x39, 0x45, + 0x1f, 0x44, 0x14, 0xa7, 0x16, 0x95, 0xa5, 0x16, 0x21, 0x31, 0x0b, 0x92, 0xf4, 0x8b, 0x0a, 0x92, + 0x21, 0xea, 0x94, 0x34, 0xb9, 0x58, 0x7d, 0x40, 0x06, 0x09, 0xf1, 0x71, 0x31, 0x79, 0xba, 0x48, + 0x30, 0x2a, 0x30, 0x6a, 0x30, 0x07, 0x31, 0x65, 0xba, 0x08, 0x09, 0x70, 0x31, 0x87, 0x84, 0xf8, + 0x48, 0x30, 0x81, 0x05, 0x98, 0x4b, 0x42, 0x7c, 0x94, 0x4a, 0xb8, 0x44, 0xc0, 0x4a, 0x3d, 0xf3, + 0x4a, 0x52, 0x8b, 0xf2, 0x12, 0x73, 0x82, 0x52, 0x0b, 0x4b, 0x53, 0x8b, 0x4b, 0x84, 0x62, 0xb8, + 0xc4, 0xc0, 0xe2, 0x21, 0x99, 0xb9, 0xa9, 0x21, 0xf9, 0x3e, 0x99, 0x65, 0xa9, 0x50, 0x19, 0xb0, + 0x69, 0xdc, 0x46, 0x2a, 0x7a, 0xc8, 0x76, 0xeb, 0x61, 0x57, 0x1b, 0x24, 0x96, 0x83, 0x55, 0x5c, + 0xa9, 0x82, 0x4b, 0x14, 0xcd, 0xd6, 0xe2, 0x82, 0xfc, 0xbc, 0xe2, 0x54, 0xa1, 0x78, 0x2e, 0x71, + 0x0c, 0xa3, 0x20, 0x52, 0x50, 0x7b, 0x55, 0x09, 0xd8, 0x0b, 0x51, 0x1c, 0x24, 0x9e, 0x83, 0x5d, + 0xc2, 0x49, 0xe2, 0xc4, 0x43, 0x39, 0x86, 0x0b, 0x0f, 0xe5, 0x18, 0x4e, 0x3c, 0x92, 0x63, 0xbc, + 0xf0, 0x48, 0x8e, 0xf1, 0xc1, 0x23, 0x39, 0xc6, 0x19, 0x8f, 0xe5, 0x18, 0x92, 0xd8, 0xc0, 0x61, + 0x67, 0x0c, 0x08, 0x00, 0x00, 0xff, 0xff, 0x65, 0xaa, 0x74, 0x2e, 0x91, 0x01, 0x00, 0x00, } diff --git a/lease/leasepb/lease.proto b/lease/leasepb/lease.proto index f2c996c8a..be414b993 100644 --- a/lease/leasepb/lease.proto +++ b/lease/leasepb/lease.proto @@ -2,6 +2,7 @@ syntax = "proto3"; package leasepb; import "gogoproto/gogo.proto"; +import "etcd/etcdserver/etcdserverpb/rpc.proto"; option (gogoproto.marshaler_all) = true; option (gogoproto.sizer_all) = true; @@ -13,3 +14,11 @@ message Lease { int64 ID = 1; int64 TTL = 2; } + +message LeaseInternalRequest { + etcdserverpb.LeaseTimeToLiveRequest LeaseTimeToLiveRequest = 1; +} + +message LeaseInternalResponse { + etcdserverpb.LeaseTimeToLiveResponse LeaseTimeToLiveResponse = 1; +} diff --git a/lease/lessor.go b/lease/lessor.go index 682d7376b..5ebe7290c 100644 --- a/lease/lessor.go +++ b/lease/lessor.go @@ -480,6 +480,20 @@ func (l *Lease) refresh(extend time.Duration) { // forever sets the expiry of lease to be forever. func (l *Lease) forever() { l.expiry = forever } +// Keys returns all the keys attached to the lease. +func (l *Lease) Keys() []string { + keys := make([]string, 0, len(l.itemSet)) + for k := range l.itemSet { + keys = append(keys, k.Key) + } + return keys +} + +// Remaining returns the remaining time of the lease. +func (l *Lease) Remaining() time.Duration { + return l.expiry.Sub(time.Now()) +} + type LeaseItem struct { Key string } diff --git a/proxy/grpcproxy/lease.go b/proxy/grpcproxy/lease.go index fe2fa1f94..4f870220b 100644 --- a/proxy/grpcproxy/lease.go +++ b/proxy/grpcproxy/lease.go @@ -41,6 +41,11 @@ func (lp *leaseProxy) LeaseRevoke(ctx context.Context, rr *pb.LeaseRevokeRequest return pb.NewLeaseClient(conn).LeaseRevoke(ctx, rr) } +func (lp *leaseProxy) LeaseTimeToLive(ctx context.Context, rr *pb.LeaseTimeToLiveRequest) (*pb.LeaseTimeToLiveResponse, error) { + conn := lp.client.ActiveConnection() + return pb.NewLeaseClient(conn).LeaseTimeToLive(ctx, rr) +} + func (lp *leaseProxy) LeaseKeepAlive(stream pb.Lease_LeaseKeepAliveServer) error { conn := lp.client.ActiveConnection() ctx, cancel := context.WithCancel(stream.Context())