From 20a3c737821166fd54f2c4091dcb45c58572ffee Mon Sep 17 00:00:00 2001 From: Connor Peet Date: Sat, 7 Oct 2017 08:56:31 -0700 Subject: [PATCH] mvcc: allow clients to assign watcher IDs This allows for watchers to be created concurrently without needing potentially complex and latency-adding queuing on the client --- .../apispec/swagger/rpc.swagger.json | 5 + etcdserver/api/v3rpc/rpctypes/error.go | 1 + etcdserver/api/v3rpc/watch.go | 110 ++-- etcdserver/etcdserverpb/rpc.pb.go | 502 ++++++++++-------- etcdserver/etcdserverpb/rpc.proto | 7 + mvcc/kv_test.go | 4 +- mvcc/watchable_store_bench_test.go | 6 +- mvcc/watchable_store_test.go | 20 +- mvcc/watcher.go | 33 +- mvcc/watcher_bench_test.go | 2 +- mvcc/watcher_test.go | 63 ++- 11 files changed, 432 insertions(+), 321 deletions(-) diff --git a/Documentation/dev-guide/apispec/swagger/rpc.swagger.json b/Documentation/dev-guide/apispec/swagger/rpc.swagger.json index 10697cc0f02e..c4a030074e88 100644 --- a/Documentation/dev-guide/apispec/swagger/rpc.swagger.json +++ b/Documentation/dev-guide/apispec/swagger/rpc.swagger.json @@ -2283,6 +2283,11 @@ "description": "start_revision is an optional revision to watch from (inclusive). No start_revision is \"now\".", "type": "string", "format": "int64" + }, + "watch_id": { + "description": "If watch_id is provided, it will be used to assign to this watcher. Since\ncreating a watcher in etcd is not a synchronous operation, this can be\nused ensure that ordering is correct when creating multiple watchers on\nthe same stream. Creating a watcher with an ID already in use on the\nstream will cause an error to be returned.", + "type": "string", + "format": "int64" } } }, diff --git a/etcdserver/api/v3rpc/rpctypes/error.go b/etcdserver/api/v3rpc/rpctypes/error.go index 446e4f6b8709..b35127f5212e 100644 --- a/etcdserver/api/v3rpc/rpctypes/error.go +++ b/etcdserver/api/v3rpc/rpctypes/error.go @@ -57,6 +57,7 @@ var ( ErrGRPCAuthNotEnabled = status.New(codes.FailedPrecondition, "etcdserver: authentication is not enabled").Err() ErrGRPCInvalidAuthToken = status.New(codes.Unauthenticated, "etcdserver: invalid auth token").Err() ErrGRPCInvalidAuthMgmt = status.New(codes.InvalidArgument, "etcdserver: invalid auth management").Err() + ErrGRPCDuplicateWatcherID = status.New(codes.InvalidArgument, "etcdserver: duplicate watcher ID").Err() ErrGRPCNoLeader = status.New(codes.Unavailable, "etcdserver: no leader").Err() ErrGRPCNotLeader = status.New(codes.FailedPrecondition, "etcdserver: not leader").Err() diff --git a/etcdserver/api/v3rpc/watch.go b/etcdserver/api/v3rpc/watch.go index c796c3386738..45718115407f 100644 --- a/etcdserver/api/v3rpc/watch.go +++ b/etcdserver/api/v3rpc/watch.go @@ -170,6 +170,60 @@ func (sws *serverWatchStream) isWatchPermitted(wcr *pb.WatchCreateRequest) bool return sws.ag.AuthStore().IsRangePermitted(authInfo, wcr.Key, wcr.RangeEnd) == nil } +func (sws *serverWatchStream) recvWatchRequest(creq *pb.WatchCreateRequest) (wr *pb.WatchResponse, id mvcc.WatchID, err error) { + if len(creq.Key) == 0 { + // \x00 is the smallest key + creq.Key = []byte{0} + } + if len(creq.RangeEnd) == 0 { + // force nil since watchstream.Watch distinguishes + // between nil and []byte{} for single key / >= + creq.RangeEnd = nil + } + if len(creq.RangeEnd) == 1 && creq.RangeEnd[0] == 0 { + // support >= key queries + creq.RangeEnd = []byte{} + } + + if !sws.isWatchPermitted(creq) { + return nil, mvcc.WatchID(creq.WatchId), rpctypes.ErrGRPCPermissionDenied + } + + filters := FiltersFromRequest(creq) + + wsrev := sws.watchStream.Rev() + rev := creq.StartRevision + if rev == 0 { + rev = wsrev + 1 + } + + id, err = sws.watchStream.Watch(mvcc.WatchID(creq.WatchId), creq.Key, creq.RangeEnd, rev, filters...) + wr = &pb.WatchResponse{ + Header: sws.newResponseHeader(wsrev), + WatchId: int64(id), + Created: true, + Canceled: false, + } + + switch { + case err == mvcc.ErrEmptyWatcherRange: + wr.Canceled = true + case err != nil: + return nil, id, err + default: + sws.mu.Lock() + if creq.ProgressNotify { + sws.progress[id] = true + } + if creq.PrevKv { + sws.prevKV[id] = true + } + sws.mu.Unlock() + } + + return wr, id, nil +} + func (sws *serverWatchStream) recvLoop() error { for { req, err := sws.gRPCStream.Recv() @@ -185,66 +239,20 @@ func (sws *serverWatchStream) recvLoop() error { if uv.CreateRequest == nil { break } - - creq := uv.CreateRequest - if len(creq.Key) == 0 { - // \x00 is the smallest key - creq.Key = []byte{0} - } - if len(creq.RangeEnd) == 0 { - // force nil since watchstream.Watch distinguishes - // between nil and []byte{} for single key / >= - creq.RangeEnd = nil - } - if len(creq.RangeEnd) == 1 && creq.RangeEnd[0] == 0 { - // support >= key queries - creq.RangeEnd = []byte{} - } - - if !sws.isWatchPermitted(creq) { - wr := &pb.WatchResponse{ + wr, id, err := sws.recvWatchRequest(uv.CreateRequest) + if err != nil { + wr = &pb.WatchResponse{ Header: sws.newResponseHeader(sws.watchStream.Rev()), - WatchId: -1, + WatchId: int64(id), Canceled: true, Created: true, - CancelReason: rpctypes.ErrGRPCPermissionDenied.Error(), - } - - select { - case sws.ctrlStream <- wr: - case <-sws.closec: + CancelReason: err.Error(), } - return nil } - filters := FiltersFromRequest(creq) - - wsrev := sws.watchStream.Rev() - rev := creq.StartRevision - if rev == 0 { - rev = wsrev + 1 - } - id := sws.watchStream.Watch(creq.Key, creq.RangeEnd, rev, filters...) - if id != -1 { - sws.mu.Lock() - if creq.ProgressNotify { - sws.progress[id] = true - } - if creq.PrevKv { - sws.prevKV[id] = true - } - sws.mu.Unlock() - } - wr := &pb.WatchResponse{ - Header: sws.newResponseHeader(wsrev), - WatchId: int64(id), - Created: true, - Canceled: id == -1, - } select { case sws.ctrlStream <- wr: case <-sws.closec: - return nil } case *pb.WatchRequest_CancelRequest: if uv.CancelRequest != nil { diff --git a/etcdserver/etcdserverpb/rpc.pb.go b/etcdserver/etcdserverpb/rpc.pb.go index 97e0c4c49e0c..392a7f7f4c44 100644 --- a/etcdserver/etcdserverpb/rpc.pb.go +++ b/etcdserver/etcdserverpb/rpc.pb.go @@ -1619,6 +1619,12 @@ type WatchCreateRequest struct { // If prev_kv is set, created watcher gets the previous KV before the event happens. // If the previous KV is already compacted, nothing will be returned. PrevKv bool `protobuf:"varint,6,opt,name=prev_kv,json=prevKv,proto3" json:"prev_kv,omitempty"` + // If watch_id is provided, it will be used to assign to this watcher. Since + // creating a watcher in etcd is not a synchronous operation, this can be + // used ensure that ordering is correct when creating multiple watchers on + // the same stream. Creating a watcher with an ID already in use on the + // stream will cause an error to be returned. + WatchId int64 `protobuf:"varint,7,opt,name=watch_id,json=watchId,proto3" json:"watch_id,omitempty"` } func (m *WatchCreateRequest) Reset() { *m = WatchCreateRequest{} } @@ -1668,6 +1674,13 @@ func (m *WatchCreateRequest) GetPrevKv() bool { return false } +func (m *WatchCreateRequest) GetWatchId() int64 { + if m != nil { + return m.WatchId + } + return 0 +} + type WatchCancelRequest struct { // watch_id is the watcher id to cancel so that no more events are transmitted. WatchId int64 `protobuf:"varint,1,opt,name=watch_id,json=watchId,proto3" json:"watch_id,omitempty"` @@ -5918,6 +5931,11 @@ func (m *WatchCreateRequest) MarshalTo(dAtA []byte) (int, error) { } i++ } + if m.WatchId != 0 { + dAtA[i] = 0x38 + i++ + i = encodeVarintRpc(dAtA, i, uint64(m.WatchId)) + } return i, nil } @@ -8425,6 +8443,9 @@ func (m *WatchCreateRequest) Size() (n int) { if m.PrevKv { n += 2 } + if m.WatchId != 0 { + n += 1 + sovRpc(uint64(m.WatchId)) + } return n } @@ -12326,6 +12347,25 @@ func (m *WatchCreateRequest) Unmarshal(dAtA []byte) error { } } m.PrevKv = bool(v != 0) + case 7: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field WatchId", wireType) + } + m.WatchId = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowRpc + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.WatchId |= (int64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } default: iNdEx = preIndex skippy, err := skipRpc(dAtA[iNdEx:]) @@ -18448,235 +18488,235 @@ var ( func init() { proto.RegisterFile("rpc.proto", fileDescriptorRpc) } var fileDescriptorRpc = []byte{ - // 3674 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xbc, 0x5b, 0x5b, 0x6f, 0x1b, 0xc7, - 0x77, 0xd7, 0x92, 0x22, 0x29, 0x1e, 0x5e, 0x44, 0x8d, 0x64, 0x9b, 0xa2, 0x6d, 0x59, 0x1e, 0xdf, - 0x64, 0x3b, 0x16, 0xff, 0x7f, 0x25, 0xed, 0x83, 0x5b, 0x04, 0x91, 0x25, 0xc6, 0x52, 0x24, 0x4b, - 0xca, 0x8a, 0x56, 0x52, 0x20, 0x28, 0xb1, 0x22, 0xc7, 0xd2, 0x42, 0xe4, 0x2e, 0xb3, 0xbb, 0xa4, - 0xa5, 0x34, 0x2d, 0x8a, 0x20, 0x41, 0xd1, 0x02, 0x7d, 0x69, 0x1e, 0x7a, 0x7b, 0x2c, 0x8a, 0x22, - 0x2f, 0x7d, 0x2b, 0xfa, 0x15, 0x8a, 0xbe, 0xb4, 0x40, 0xbf, 0x40, 0x91, 0xf6, 0xa5, 0xdf, 0xa1, - 0x45, 0xff, 0x98, 0xdb, 0xee, 0xec, 0x72, 0x97, 0x52, 0xc2, 0x24, 0x2f, 0xf2, 0xce, 0x99, 0x33, - 0xe7, 0x9c, 0x39, 0x33, 0xe7, 0x9c, 0x99, 0xdf, 0xd0, 0x90, 0x77, 0xfa, 0xed, 0xd5, 0xbe, 0x63, - 0x7b, 0x36, 0x2a, 0x12, 0xaf, 0xdd, 0x71, 0x89, 0x33, 0x24, 0x4e, 0xff, 0xb8, 0xb6, 0x70, 0x62, - 0x9f, 0xd8, 0xac, 0xa3, 0x4e, 0xbf, 0x38, 0x4f, 0x6d, 0x91, 0xf2, 0xd4, 0x7b, 0xc3, 0x76, 0x9b, - 0xfd, 0xe9, 0x1f, 0xd7, 0xcf, 0x86, 0xa2, 0xeb, 0x26, 0xeb, 0x32, 0x06, 0xde, 0x29, 0xfb, 0xd3, - 0x3f, 0x66, 0xff, 0x88, 0xce, 0x5b, 0x27, 0xb6, 0x7d, 0xd2, 0x25, 0x75, 0xa3, 0x6f, 0xd6, 0x0d, - 0xcb, 0xb2, 0x3d, 0xc3, 0x33, 0x6d, 0xcb, 0xe5, 0xbd, 0xf8, 0x1b, 0x0d, 0xca, 0x3a, 0x71, 0xfb, - 0xb6, 0xe5, 0x92, 0x2d, 0x62, 0x74, 0x88, 0x83, 0x6e, 0x03, 0xb4, 0xbb, 0x03, 0xd7, 0x23, 0x4e, - 0xcb, 0xec, 0x54, 0xb5, 0x65, 0x6d, 0x65, 0x5a, 0xcf, 0x0b, 0xca, 0x76, 0x07, 0xdd, 0x84, 0x7c, - 0x8f, 0xf4, 0x8e, 0x79, 0x6f, 0x8a, 0xf5, 0xce, 0x70, 0xc2, 0x76, 0x07, 0xd5, 0x60, 0xc6, 0x21, - 0x43, 0xd3, 0x35, 0x6d, 0xab, 0x9a, 0x5e, 0xd6, 0x56, 0xd2, 0xba, 0xdf, 0xa6, 0x03, 0x1d, 0xe3, - 0x8d, 0xd7, 0xf2, 0x88, 0xd3, 0xab, 0x4e, 0xf3, 0x81, 0x94, 0xd0, 0x24, 0x4e, 0x0f, 0x7f, 0x9d, - 0x81, 0xa2, 0x6e, 0x58, 0x27, 0x44, 0x27, 0x9f, 0x0f, 0x88, 0xeb, 0xa1, 0x0a, 0xa4, 0xcf, 0xc8, - 0x05, 0x53, 0x5f, 0xd4, 0xe9, 0x27, 0x1f, 0x6f, 0x9d, 0x90, 0x16, 0xb1, 0xb8, 0xe2, 0x22, 0x1d, - 0x6f, 0x9d, 0x90, 0x86, 0xd5, 0x41, 0x0b, 0x90, 0xe9, 0x9a, 0x3d, 0xd3, 0x13, 0x5a, 0x79, 0x23, - 0x64, 0xce, 0x74, 0xc4, 0x9c, 0x0d, 0x00, 0xd7, 0x76, 0xbc, 0x96, 0xed, 0x74, 0x88, 0x53, 0xcd, - 0x2c, 0x6b, 0x2b, 0xe5, 0xb5, 0xfb, 0xab, 0xea, 0x42, 0xac, 0xaa, 0x06, 0xad, 0x1e, 0xda, 0x8e, - 0xb7, 0x4f, 0x79, 0xf5, 0xbc, 0x2b, 0x3f, 0xd1, 0x87, 0x50, 0x60, 0x42, 0x3c, 0xc3, 0x39, 0x21, - 0x5e, 0x35, 0xcb, 0xa4, 0x3c, 0xb8, 0x44, 0x4a, 0x93, 0x31, 0xeb, 0x4c, 0x3d, 0xff, 0x46, 0x18, - 0x8a, 0x2e, 0x71, 0x4c, 0xa3, 0x6b, 0x7e, 0x61, 0x1c, 0x77, 0x49, 0x35, 0xb7, 0xac, 0xad, 0xcc, - 0xe8, 0x21, 0x1a, 0x9d, 0xff, 0x19, 0xb9, 0x70, 0x5b, 0xb6, 0xd5, 0xbd, 0xa8, 0xce, 0x30, 0x86, - 0x19, 0x4a, 0xd8, 0xb7, 0xba, 0x17, 0x6c, 0xd1, 0xec, 0x81, 0xe5, 0xf1, 0xde, 0x3c, 0xeb, 0xcd, - 0x33, 0x0a, 0xeb, 0x5e, 0x81, 0x4a, 0xcf, 0xb4, 0x5a, 0x3d, 0xbb, 0xd3, 0xf2, 0x1d, 0x02, 0xcc, - 0x21, 0xe5, 0x9e, 0x69, 0xbd, 0xb2, 0x3b, 0xba, 0x74, 0x0b, 0xe5, 0x34, 0xce, 0xc3, 0x9c, 0x05, - 0xc1, 0x69, 0x9c, 0xab, 0x9c, 0xab, 0x30, 0x4f, 0x65, 0xb6, 0x1d, 0x62, 0x78, 0x24, 0x60, 0x2e, - 0x32, 0xe6, 0xb9, 0x9e, 0x69, 0x6d, 0xb0, 0x9e, 0x10, 0xbf, 0x71, 0x3e, 0xc2, 0x5f, 0x12, 0xfc, - 0xc6, 0x79, 0x98, 0x1f, 0xaf, 0x42, 0xde, 0xf7, 0x39, 0x9a, 0x81, 0xe9, 0xbd, 0xfd, 0xbd, 0x46, - 0x65, 0x0a, 0x01, 0x64, 0xd7, 0x0f, 0x37, 0x1a, 0x7b, 0x9b, 0x15, 0x0d, 0x15, 0x20, 0xb7, 0xd9, - 0xe0, 0x8d, 0x14, 0x7e, 0x01, 0x10, 0x78, 0x17, 0xe5, 0x20, 0xbd, 0xd3, 0xf8, 0xbd, 0xca, 0x14, - 0xe5, 0x39, 0x6a, 0xe8, 0x87, 0xdb, 0xfb, 0x7b, 0x15, 0x8d, 0x0e, 0xde, 0xd0, 0x1b, 0xeb, 0xcd, - 0x46, 0x25, 0x45, 0x39, 0x5e, 0xed, 0x6f, 0x56, 0xd2, 0x28, 0x0f, 0x99, 0xa3, 0xf5, 0xdd, 0xd7, - 0x8d, 0xca, 0x34, 0xfe, 0x56, 0x83, 0x92, 0x58, 0x2f, 0x1e, 0x13, 0xe8, 0x3d, 0xc8, 0x9e, 0xb2, - 0xb8, 0x60, 0x5b, 0xb1, 0xb0, 0x76, 0x2b, 0xb2, 0xb8, 0xa1, 0xd8, 0xd1, 0x05, 0x2f, 0xc2, 0x90, - 0x3e, 0x1b, 0xba, 0xd5, 0xd4, 0x72, 0x7a, 0xa5, 0xb0, 0x56, 0x59, 0xe5, 0x01, 0xbb, 0xba, 0x43, - 0x2e, 0x8e, 0x8c, 0xee, 0x80, 0xe8, 0xb4, 0x13, 0x21, 0x98, 0xee, 0xd9, 0x0e, 0x61, 0x3b, 0x76, - 0x46, 0x67, 0xdf, 0x74, 0x1b, 0xb3, 0x45, 0x13, 0xbb, 0x95, 0x37, 0xf0, 0x77, 0x1a, 0xc0, 0xc1, - 0xc0, 0x4b, 0x0e, 0x8d, 0x05, 0xc8, 0x0c, 0xa9, 0x60, 0x11, 0x16, 0xbc, 0xc1, 0x62, 0x82, 0x18, - 0x2e, 0xf1, 0x63, 0x82, 0x36, 0xd0, 0x0d, 0xc8, 0xf5, 0x1d, 0x32, 0x6c, 0x9d, 0x0d, 0x99, 0x92, - 0x19, 0x3d, 0x4b, 0x9b, 0x3b, 0x43, 0x74, 0x17, 0x8a, 0xe6, 0x89, 0x65, 0x3b, 0xa4, 0xc5, 0x65, - 0x65, 0x58, 0x6f, 0x81, 0xd3, 0x98, 0xdd, 0x0a, 0x0b, 0x17, 0x9c, 0x55, 0x59, 0x76, 0x29, 0x09, - 0x5b, 0x50, 0x60, 0xa6, 0x4e, 0xe4, 0xbe, 0xc7, 0x81, 0x8d, 0x29, 0x36, 0x6c, 0xd4, 0x85, 0xc2, - 0x6a, 0xfc, 0x19, 0xa0, 0x4d, 0xd2, 0x25, 0x1e, 0x99, 0x24, 0x7b, 0x28, 0x3e, 0x49, 0xab, 0x3e, - 0xc1, 0x7f, 0xa1, 0xc1, 0x7c, 0x48, 0xfc, 0x44, 0xd3, 0xaa, 0x42, 0xae, 0xc3, 0x84, 0x71, 0x0b, - 0xd2, 0xba, 0x6c, 0xa2, 0xa7, 0x30, 0x23, 0x0c, 0x70, 0xab, 0xe9, 0x84, 0x4d, 0x93, 0xe3, 0x36, - 0xb9, 0xf8, 0xbb, 0x14, 0xe4, 0xc5, 0x44, 0xf7, 0xfb, 0x68, 0x1d, 0x4a, 0x0e, 0x6f, 0xb4, 0xd8, - 0x7c, 0x84, 0x45, 0xb5, 0xe4, 0x24, 0xb4, 0x35, 0xa5, 0x17, 0xc5, 0x10, 0x46, 0x46, 0xbf, 0x03, - 0x05, 0x29, 0xa2, 0x3f, 0xf0, 0x84, 0xcb, 0xab, 0x61, 0x01, 0xc1, 0xfe, 0xdb, 0x9a, 0xd2, 0x41, - 0xb0, 0x1f, 0x0c, 0x3c, 0xd4, 0x84, 0x05, 0x39, 0x98, 0xcf, 0x46, 0x98, 0x91, 0x66, 0x52, 0x96, - 0xc3, 0x52, 0x46, 0x97, 0x6a, 0x6b, 0x4a, 0x47, 0x62, 0xbc, 0xd2, 0xa9, 0x9a, 0xe4, 0x9d, 0xf3, - 0xe4, 0x3d, 0x62, 0x52, 0xf3, 0xdc, 0x1a, 0x35, 0xa9, 0x79, 0x6e, 0xbd, 0xc8, 0x43, 0x4e, 0xb4, - 0xf0, 0x3f, 0xa7, 0x00, 0xe4, 0x6a, 0xec, 0xf7, 0xd1, 0x26, 0x94, 0x1d, 0xd1, 0x0a, 0x79, 0xeb, - 0x66, 0xac, 0xb7, 0xc4, 0x22, 0x4e, 0xe9, 0x25, 0x39, 0x88, 0x1b, 0xf7, 0x3e, 0x14, 0x7d, 0x29, - 0x81, 0xc3, 0x16, 0x63, 0x1c, 0xe6, 0x4b, 0x28, 0xc8, 0x01, 0xd4, 0x65, 0x9f, 0xc0, 0x35, 0x7f, - 0x7c, 0x8c, 0xcf, 0xee, 0x8e, 0xf1, 0x99, 0x2f, 0x70, 0x5e, 0x4a, 0x50, 0xbd, 0xa6, 0x1a, 0x16, - 0xb8, 0x6d, 0x31, 0xc6, 0x6d, 0xa3, 0x86, 0x51, 0xc7, 0x01, 0xad, 0x97, 0xbc, 0x89, 0xff, 0x27, - 0x0d, 0xb9, 0x0d, 0xbb, 0xd7, 0x37, 0x1c, 0xba, 0x1a, 0x59, 0x87, 0xb8, 0x83, 0xae, 0xc7, 0xdc, - 0x55, 0x5e, 0xbb, 0x17, 0x96, 0x28, 0xd8, 0xe4, 0xbf, 0x3a, 0x63, 0xd5, 0xc5, 0x10, 0x3a, 0x58, - 0x94, 0xc7, 0xd4, 0x15, 0x06, 0x8b, 0xe2, 0x28, 0x86, 0xc8, 0x40, 0x4e, 0x07, 0x81, 0x5c, 0x83, - 0xdc, 0x90, 0x38, 0x41, 0x49, 0xdf, 0x9a, 0xd2, 0x25, 0x01, 0x3d, 0x86, 0xd9, 0x68, 0x79, 0xc9, - 0x08, 0x9e, 0x72, 0x3b, 0x5c, 0x8d, 0xee, 0x41, 0x31, 0x54, 0xe3, 0xb2, 0x82, 0xaf, 0xd0, 0x53, - 0x4a, 0xdc, 0x75, 0x99, 0x57, 0x69, 0x3d, 0x2e, 0x6e, 0x4d, 0xc9, 0xcc, 0x7a, 0x5d, 0x66, 0xd6, - 0x19, 0x31, 0x4a, 0xe4, 0xd6, 0x50, 0x92, 0xf9, 0x20, 0x9c, 0x64, 0xf0, 0x07, 0x50, 0x0a, 0x39, - 0x88, 0xd6, 0x9d, 0xc6, 0xc7, 0xaf, 0xd7, 0x77, 0x79, 0x91, 0x7a, 0xc9, 0xea, 0x92, 0x5e, 0xd1, - 0x68, 0xad, 0xdb, 0x6d, 0x1c, 0x1e, 0x56, 0x52, 0xa8, 0x04, 0xf9, 0xbd, 0xfd, 0x66, 0x8b, 0x73, - 0xa5, 0xf1, 0x4b, 0x5f, 0x82, 0x28, 0x72, 0x4a, 0x6d, 0x9b, 0x52, 0x6a, 0x9b, 0x26, 0x6b, 0x5b, - 0x2a, 0xa8, 0x6d, 0xac, 0xcc, 0xed, 0x36, 0xd6, 0x0f, 0x1b, 0x95, 0xe9, 0x17, 0x65, 0x28, 0x72, - 0xff, 0xb6, 0x06, 0x16, 0x2d, 0xb5, 0x7f, 0xa7, 0x01, 0x04, 0xd1, 0x84, 0xea, 0x90, 0x6b, 0x73, - 0x3d, 0x55, 0x8d, 0x25, 0xa3, 0x6b, 0xb1, 0x4b, 0xa6, 0x4b, 0x2e, 0xf4, 0x6b, 0xc8, 0xb9, 0x83, - 0x76, 0x9b, 0xb8, 0xb2, 0xe4, 0xdd, 0x88, 0xe6, 0x43, 0x91, 0xad, 0x74, 0xc9, 0x47, 0x87, 0xbc, - 0x31, 0xcc, 0xee, 0x80, 0x15, 0xc0, 0xf1, 0x43, 0x04, 0x1f, 0xfe, 0x6b, 0x0d, 0x0a, 0xca, 0xe6, - 0xfd, 0x91, 0x49, 0xf8, 0x16, 0xe4, 0x99, 0x0d, 0xa4, 0x23, 0xd2, 0xf0, 0x8c, 0x1e, 0x10, 0xd0, - 0x6f, 0x43, 0x5e, 0x46, 0x80, 0xcc, 0xc4, 0xd5, 0x78, 0xb1, 0xfb, 0x7d, 0x3d, 0x60, 0xc5, 0x3b, - 0x30, 0xc7, 0xbc, 0xd2, 0xa6, 0x87, 0x6b, 0xe9, 0x47, 0xf5, 0xf8, 0xa9, 0x45, 0x8e, 0x9f, 0x35, - 0x98, 0xe9, 0x9f, 0x5e, 0xb8, 0x66, 0xdb, 0xe8, 0x0a, 0x2b, 0xfc, 0x36, 0xfe, 0x08, 0x90, 0x2a, - 0x6c, 0x92, 0xe9, 0xe2, 0x12, 0x14, 0xb6, 0x0c, 0xf7, 0x54, 0x98, 0x84, 0x9f, 0x42, 0x89, 0x36, - 0x77, 0x8e, 0xae, 0x60, 0x23, 0xbb, 0x1c, 0x48, 0xee, 0x89, 0x7c, 0x8e, 0x60, 0xfa, 0xd4, 0x70, - 0x4f, 0xd9, 0x44, 0x4b, 0x3a, 0xfb, 0x46, 0x8f, 0xa1, 0xd2, 0xe6, 0x93, 0x6c, 0x45, 0xae, 0x0c, - 0xb3, 0x82, 0xee, 0x9f, 0x04, 0x3f, 0x85, 0x22, 0x9f, 0xc3, 0x4f, 0x6d, 0x04, 0x9e, 0x83, 0xd9, - 0x43, 0xcb, 0xe8, 0xbb, 0xa7, 0xb6, 0xac, 0x6e, 0x74, 0xd2, 0x95, 0x80, 0x36, 0x91, 0xc6, 0x47, - 0x30, 0xeb, 0x90, 0x9e, 0x61, 0x5a, 0xa6, 0x75, 0xd2, 0x3a, 0xbe, 0xf0, 0x88, 0x2b, 0x2e, 0x4c, - 0x65, 0x9f, 0xfc, 0x82, 0x52, 0xa9, 0x69, 0xc7, 0x5d, 0xfb, 0x58, 0xa4, 0x39, 0xf6, 0x8d, 0xff, - 0x49, 0x83, 0xe2, 0x27, 0x86, 0xd7, 0x96, 0x4b, 0x87, 0xb6, 0xa1, 0xec, 0x27, 0x37, 0x46, 0x11, - 0xb6, 0x44, 0x4a, 0x2c, 0x1b, 0x23, 0x8f, 0xd2, 0xb2, 0x3a, 0x96, 0xda, 0x2a, 0x81, 0x89, 0x32, - 0xac, 0x36, 0xe9, 0xfa, 0xa2, 0x52, 0xc9, 0xa2, 0x18, 0xa3, 0x2a, 0x4a, 0x25, 0xbc, 0x98, 0x0d, - 0x8e, 0x1f, 0x3c, 0x97, 0xfc, 0x4d, 0x0a, 0xd0, 0xa8, 0x0d, 0x3f, 0xf4, 0x44, 0xf6, 0x00, 0xca, - 0xae, 0x67, 0x38, 0x23, 0x7b, 0xa3, 0xc4, 0xa8, 0x7e, 0x82, 0x7e, 0x04, 0xb3, 0x7d, 0xc7, 0x3e, - 0x71, 0x88, 0xeb, 0xb6, 0x2c, 0xdb, 0x33, 0xdf, 0x5c, 0x88, 0x43, 0x6d, 0x59, 0x92, 0xf7, 0x18, - 0x15, 0x35, 0x20, 0xf7, 0xc6, 0xec, 0x7a, 0xc4, 0x71, 0xab, 0x99, 0xe5, 0xf4, 0x4a, 0x79, 0xed, - 0xe9, 0x65, 0x5e, 0x5b, 0xfd, 0x90, 0xf1, 0x37, 0x2f, 0xfa, 0x44, 0x97, 0x63, 0xd5, 0x83, 0x62, - 0x36, 0x74, 0x50, 0x7c, 0x00, 0x10, 0xf0, 0xd3, 0x54, 0xbb, 0xb7, 0x7f, 0xf0, 0xba, 0x59, 0x99, - 0x42, 0x45, 0x98, 0xd9, 0xdb, 0xdf, 0x6c, 0xec, 0x36, 0x68, 0x5e, 0xc6, 0x75, 0xe9, 0x1b, 0xd5, - 0x87, 0x68, 0x11, 0x66, 0xde, 0x52, 0xaa, 0xbc, 0x6f, 0xa7, 0xf5, 0x1c, 0x6b, 0x6f, 0x77, 0xf0, - 0x9f, 0xa7, 0xa0, 0x24, 0x76, 0xc1, 0x44, 0x5b, 0x51, 0x55, 0x91, 0x0a, 0xa9, 0xa0, 0xa7, 0x52, - 0xbe, 0x3b, 0x3a, 0xe2, 0xf0, 0x2b, 0x9b, 0x34, 0x37, 0xf0, 0xc5, 0x26, 0x1d, 0xe1, 0x56, 0xbf, - 0x1d, 0x1b, 0xbe, 0x99, 0xd8, 0xf0, 0x45, 0xf7, 0xa0, 0xe4, 0xef, 0x36, 0xc3, 0x15, 0xb5, 0x36, - 0xaf, 0x17, 0xe5, 0x46, 0xa2, 0x34, 0xf4, 0x00, 0xb2, 0x64, 0x48, 0x2c, 0xcf, 0xad, 0x16, 0x58, - 0xd6, 0x2d, 0xc9, 0xf3, 0x6f, 0x83, 0x52, 0x75, 0xd1, 0x89, 0x7f, 0x0b, 0xe6, 0xd8, 0x3d, 0xe3, - 0xa5, 0x63, 0x58, 0xea, 0x85, 0xa8, 0xd9, 0xdc, 0x15, 0xae, 0xa3, 0x9f, 0xa8, 0x0c, 0xa9, 0xed, - 0x4d, 0x31, 0xd1, 0xd4, 0xf6, 0x26, 0xfe, 0x4a, 0x03, 0xa4, 0x8e, 0x9b, 0xc8, 0x97, 0x11, 0xe1, - 0x52, 0x7d, 0x3a, 0x50, 0xbf, 0x00, 0x19, 0xe2, 0x38, 0xb6, 0xc3, 0xbc, 0x96, 0xd7, 0x79, 0x03, - 0xdf, 0x17, 0x36, 0xe8, 0x64, 0x68, 0x9f, 0xf9, 0x81, 0xc1, 0xa5, 0x69, 0xbe, 0xa9, 0x3b, 0x30, - 0x1f, 0xe2, 0x9a, 0x28, 0xfb, 0x3f, 0x82, 0x6b, 0x4c, 0xd8, 0x0e, 0x21, 0xfd, 0xf5, 0xae, 0x39, - 0x4c, 0xd4, 0xda, 0x87, 0xeb, 0x51, 0xc6, 0x9f, 0xd7, 0x47, 0xf8, 0x77, 0x85, 0xc6, 0xa6, 0xd9, - 0x23, 0x4d, 0x7b, 0x37, 0xd9, 0x36, 0x9a, 0x1d, 0xcf, 0xc8, 0x85, 0x2b, 0xca, 0x24, 0xfb, 0xc6, - 0x7f, 0xaf, 0xc1, 0x8d, 0x91, 0xe1, 0x3f, 0xf3, 0xaa, 0x2e, 0x01, 0x9c, 0xd0, 0xed, 0x43, 0x3a, - 0xb4, 0x83, 0xdf, 0xd0, 0x15, 0x8a, 0x6f, 0x27, 0x4d, 0x30, 0x45, 0x61, 0xe7, 0x82, 0x58, 0x73, - 0xf6, 0xc7, 0x95, 0x35, 0xe6, 0x36, 0x14, 0x18, 0xe1, 0xd0, 0x33, 0xbc, 0x81, 0x3b, 0xb2, 0x18, - 0x7f, 0x24, 0xb6, 0x80, 0x1c, 0x34, 0xd1, 0xbc, 0x7e, 0x0d, 0x59, 0x76, 0x38, 0x95, 0x47, 0xb3, - 0xc8, 0x6d, 0x40, 0xb1, 0x43, 0x17, 0x8c, 0xf8, 0x14, 0xb2, 0xaf, 0x18, 0xa2, 0xa7, 0x58, 0x36, - 0x2d, 0x97, 0xc2, 0x32, 0x7a, 0x1c, 0x67, 0xc8, 0xeb, 0xec, 0x9b, 0x9d, 0x64, 0x08, 0x71, 0x5e, - 0xeb, 0xbb, 0xfc, 0xc4, 0x94, 0xd7, 0xfd, 0x36, 0x75, 0x59, 0xbb, 0x6b, 0x12, 0xcb, 0x63, 0xbd, - 0xd3, 0xac, 0x57, 0xa1, 0xe0, 0x55, 0xa8, 0x70, 0x4d, 0xeb, 0x9d, 0x8e, 0x72, 0x22, 0xf1, 0xe5, - 0x69, 0x61, 0x79, 0xf8, 0x1f, 0x34, 0x98, 0x53, 0x06, 0x4c, 0xe4, 0x98, 0x77, 0x20, 0xcb, 0x71, - 0x4b, 0x51, 0xfc, 0x16, 0xc2, 0xa3, 0xb8, 0x1a, 0x5d, 0xf0, 0xa0, 0x55, 0xc8, 0xf1, 0x2f, 0x79, - 0x2c, 0x8c, 0x67, 0x97, 0x4c, 0xf8, 0x01, 0xcc, 0x0b, 0x12, 0xe9, 0xd9, 0x71, 0x7b, 0x9b, 0x39, - 0x14, 0x7f, 0x09, 0x0b, 0x61, 0xb6, 0x89, 0xa6, 0xa4, 0x18, 0x99, 0xba, 0x8a, 0x91, 0xeb, 0xd2, - 0xc8, 0xd7, 0xfd, 0x8e, 0x52, 0xab, 0xa3, 0xab, 0xae, 0xae, 0x48, 0x2a, 0xb2, 0x22, 0xfe, 0x04, - 0xa4, 0x88, 0x5f, 0x74, 0x02, 0xf3, 0x72, 0x3b, 0xec, 0x9a, 0xae, 0x7f, 0x82, 0xfb, 0x02, 0x90, - 0x4a, 0xfc, 0xa5, 0x0d, 0xda, 0x24, 0x6f, 0x1c, 0xe3, 0xa4, 0x47, 0xfc, 0xfa, 0x44, 0xcf, 0xf3, - 0x2a, 0x71, 0xa2, 0x8c, 0x5e, 0x87, 0xb9, 0x57, 0xf6, 0x90, 0xa6, 0x06, 0x4a, 0x0d, 0x42, 0x86, - 0xdf, 0xe7, 0xfc, 0x65, 0xf3, 0xdb, 0x54, 0xb9, 0x3a, 0x60, 0x22, 0xe5, 0xff, 0xa6, 0x41, 0x71, - 0xbd, 0x6b, 0x38, 0x3d, 0xa9, 0xf8, 0x7d, 0xc8, 0xf2, 0x5b, 0x8a, 0x00, 0x06, 0x1e, 0x86, 0xc5, - 0xa8, 0xbc, 0xbc, 0xb1, 0xce, 0xef, 0x34, 0x62, 0x14, 0x35, 0x5c, 0xbc, 0x1d, 0x6c, 0x46, 0xde, - 0x12, 0x36, 0xd1, 0x33, 0xc8, 0x18, 0x74, 0x08, 0x4b, 0xc1, 0xe5, 0xe8, 0xfd, 0x90, 0x49, 0x63, - 0x87, 0x33, 0xce, 0x85, 0xdf, 0x83, 0x82, 0xa2, 0x81, 0xde, 0x80, 0x5f, 0x36, 0xc4, 0x01, 0x6c, - 0x7d, 0xa3, 0xb9, 0x7d, 0xc4, 0x2f, 0xc6, 0x65, 0x80, 0xcd, 0x86, 0xdf, 0x4e, 0xe1, 0x4f, 0xc5, - 0x28, 0x91, 0xef, 0x54, 0x7b, 0xb4, 0x24, 0x7b, 0x52, 0x57, 0xb2, 0xe7, 0x1c, 0x4a, 0x62, 0xfa, - 0x93, 0xa6, 0x6f, 0x26, 0x2f, 0x21, 0x7d, 0x2b, 0xc6, 0xeb, 0x82, 0x11, 0xcf, 0x42, 0x49, 0x24, - 0x74, 0xb1, 0xff, 0xfe, 0x55, 0x83, 0xb2, 0xa4, 0x4c, 0x0a, 0x60, 0x4a, 0xec, 0x85, 0x57, 0x00, - 0x1f, 0x79, 0xb9, 0x0e, 0xd9, 0xce, 0xf1, 0xa1, 0xf9, 0x85, 0x04, 0x9b, 0x45, 0x8b, 0xd2, 0xbb, - 0x5c, 0x0f, 0x7f, 0xf1, 0x11, 0x2d, 0x7a, 0x0b, 0x77, 0x8c, 0x37, 0xde, 0xb6, 0xd5, 0x21, 0xe7, - 0xec, 0xdc, 0x38, 0xad, 0x07, 0x04, 0x76, 0x29, 0x15, 0x2f, 0x43, 0xec, 0xb0, 0xa8, 0xbe, 0x14, - 0xcd, 0xc3, 0xdc, 0xfa, 0xc0, 0x3b, 0x6d, 0x58, 0xc6, 0x71, 0x57, 0x66, 0x2c, 0x5a, 0x66, 0x29, - 0x71, 0xd3, 0x74, 0x55, 0x6a, 0x03, 0xe6, 0x29, 0x95, 0x58, 0x9e, 0xd9, 0x56, 0xd2, 0x9b, 0x2c, - 0x62, 0x5a, 0xa4, 0x88, 0x19, 0xae, 0xfb, 0xd6, 0x76, 0x3a, 0x62, 0x6a, 0x7e, 0x1b, 0x6f, 0x72, - 0xe1, 0xaf, 0xdd, 0x50, 0x99, 0xfa, 0xa1, 0x52, 0x56, 0x02, 0x29, 0x2f, 0x89, 0x37, 0x46, 0x0a, - 0x7e, 0x0a, 0xd7, 0x24, 0xa7, 0x00, 0xf7, 0xc6, 0x30, 0xef, 0xc3, 0x6d, 0xc9, 0xbc, 0x71, 0x4a, - 0x6f, 0x4f, 0x07, 0x42, 0xe1, 0x8f, 0xb5, 0xf3, 0x05, 0x54, 0x7d, 0x3b, 0xd9, 0x61, 0xd9, 0xee, - 0xaa, 0x06, 0x0c, 0x5c, 0xb1, 0x67, 0xf2, 0x3a, 0xfb, 0xa6, 0x34, 0xc7, 0xee, 0xfa, 0x47, 0x02, - 0xfa, 0x8d, 0x37, 0x60, 0x51, 0xca, 0x10, 0xc7, 0xd8, 0xb0, 0x90, 0x11, 0x83, 0xe2, 0x84, 0x08, - 0x87, 0xd1, 0xa1, 0xe3, 0xdd, 0xae, 0x72, 0x86, 0x5d, 0xcb, 0x64, 0x6a, 0x8a, 0xcc, 0x6b, 0x7c, - 0x47, 0x50, 0xc3, 0xd4, 0x8a, 0x21, 0xc8, 0x54, 0x80, 0x4a, 0x16, 0x0b, 0x41, 0xc9, 0x23, 0x0b, - 0x31, 0x22, 0xfa, 0x33, 0x58, 0xf2, 0x8d, 0xa0, 0x7e, 0x3b, 0x20, 0x4e, 0xcf, 0x74, 0x5d, 0x05, - 0x0e, 0x8a, 0x9b, 0xf8, 0x43, 0x98, 0xee, 0x13, 0x91, 0x53, 0x0a, 0x6b, 0x68, 0x95, 0xbf, 0xdf, - 0xae, 0x2a, 0x83, 0x59, 0x3f, 0xee, 0xc0, 0x1d, 0x29, 0x9d, 0x7b, 0x34, 0x56, 0x7c, 0xd4, 0x28, - 0x79, 0xeb, 0xe6, 0x6e, 0x1d, 0xbd, 0x75, 0xa7, 0xf9, 0xda, 0xfb, 0x10, 0xe5, 0x47, 0xdc, 0x91, - 0x32, 0xb6, 0x26, 0xaa, 0x15, 0x3b, 0xdc, 0xa7, 0x7e, 0x48, 0x4e, 0x24, 0xec, 0x18, 0x16, 0xc2, - 0x91, 0x3c, 0x51, 0x1a, 0x5b, 0x80, 0x8c, 0x67, 0x9f, 0x11, 0x99, 0xc4, 0x78, 0x43, 0x1a, 0xec, - 0x87, 0xf9, 0x44, 0x06, 0x1b, 0x81, 0x30, 0xb6, 0x25, 0x27, 0xb5, 0x97, 0xae, 0xa6, 0x3c, 0x7c, - 0xf1, 0x06, 0xde, 0x83, 0xeb, 0xd1, 0x34, 0x31, 0x91, 0xc9, 0x47, 0x7c, 0x03, 0xc7, 0x65, 0x92, - 0x89, 0xe4, 0x7e, 0x1c, 0x24, 0x03, 0x25, 0xa1, 0x4c, 0x24, 0x52, 0x87, 0x5a, 0x5c, 0x7e, 0xf9, - 0x29, 0xf6, 0xab, 0x9f, 0x6e, 0x26, 0x12, 0xe6, 0x06, 0xc2, 0x26, 0x5f, 0xfe, 0x20, 0x47, 0xa4, - 0xc7, 0xe6, 0x08, 0x11, 0x24, 0x41, 0x16, 0xfb, 0x19, 0x36, 0x9d, 0xd0, 0x11, 0x24, 0xd0, 0x49, - 0x75, 0xd0, 0x1a, 0xe2, 0xeb, 0x60, 0x0d, 0xb9, 0xb1, 0xd5, 0xb4, 0x3b, 0xd1, 0x62, 0x7c, 0x12, - 0xe4, 0xce, 0x91, 0xcc, 0x3c, 0x91, 0xe0, 0x4f, 0x61, 0x39, 0x39, 0x29, 0x4f, 0x22, 0xf9, 0x49, - 0x1d, 0xf2, 0xfe, 0x81, 0x52, 0xf9, 0xed, 0x43, 0x01, 0x72, 0x7b, 0xfb, 0x87, 0x07, 0xeb, 0x1b, - 0x0d, 0xfe, 0xe3, 0x87, 0x8d, 0x7d, 0x5d, 0x7f, 0x7d, 0xd0, 0xac, 0xa4, 0xd6, 0xfe, 0x2f, 0x0d, - 0xa9, 0x9d, 0x23, 0xf4, 0xfb, 0x90, 0xe1, 0x2f, 0x81, 0x63, 0x9e, 0x7f, 0x6b, 0xe3, 0x1e, 0x3b, - 0xf1, 0xad, 0xaf, 0xfe, 0xe3, 0xbf, 0xbf, 0x4d, 0x5d, 0xc7, 0x73, 0xf5, 0xe1, 0xbb, 0x46, 0xb7, - 0x7f, 0x6a, 0xd4, 0xcf, 0x86, 0x75, 0x56, 0x20, 0x9e, 0x6b, 0x4f, 0xd0, 0x11, 0xa4, 0x0f, 0x06, - 0x1e, 0x4a, 0x7c, 0x1b, 0xae, 0x25, 0x3f, 0x82, 0xe2, 0x1a, 0x93, 0xbc, 0x80, 0x67, 0x55, 0xc9, - 0xfd, 0x81, 0x47, 0xe5, 0x0e, 0xa1, 0xa0, 0xbe, 0x63, 0x5e, 0xfa, 0x6a, 0x5c, 0xbb, 0xfc, 0x8d, - 0x14, 0x63, 0xa6, 0xef, 0x16, 0xbe, 0xa1, 0xea, 0xe3, 0xcf, 0xad, 0xea, 0x7c, 0x9a, 0xe7, 0x16, - 0x4a, 0x7c, 0x58, 0xae, 0x25, 0xbf, 0x9d, 0xc6, 0xcf, 0xc7, 0x3b, 0xb7, 0xa8, 0x5c, 0x5b, 0xbc, - 0x9d, 0xb6, 0x3d, 0x74, 0x27, 0xe6, 0xed, 0x4c, 0x7d, 0x25, 0xaa, 0x2d, 0x27, 0x33, 0x08, 0x4d, - 0x77, 0x99, 0xa6, 0x9b, 0xf8, 0xba, 0xaa, 0xa9, 0xed, 0xf3, 0x3d, 0xd7, 0x9e, 0xac, 0x9d, 0x42, - 0x86, 0xc1, 0xc4, 0xa8, 0x25, 0x3f, 0x6a, 0x31, 0x00, 0x77, 0xc2, 0x0e, 0x08, 0x01, 0xcc, 0x78, - 0x91, 0x69, 0x9b, 0xc7, 0x65, 0x5f, 0x1b, 0x43, 0x8a, 0x9f, 0x6b, 0x4f, 0x56, 0xb4, 0x5f, 0x69, - 0x6b, 0xff, 0x3b, 0x0d, 0x19, 0x06, 0x1a, 0xa1, 0x3e, 0x40, 0x80, 0xa9, 0x46, 0xe7, 0x39, 0x82, - 0xd2, 0x46, 0xe7, 0x39, 0x0a, 0xc7, 0xe2, 0x3b, 0x4c, 0xf3, 0x22, 0x5e, 0xf0, 0x35, 0x33, 0x40, - 0xaa, 0xce, 0x30, 0x36, 0xea, 0xd6, 0xb7, 0x02, 0x37, 0xe3, 0xd1, 0x86, 0xe2, 0x24, 0x86, 0xc0, - 0xd5, 0xe8, 0x36, 0x89, 0x01, 0x56, 0xf1, 0x3d, 0xa6, 0xf4, 0x36, 0xae, 0xaa, 0xce, 0xe5, 0x7a, - 0x1d, 0xc6, 0x49, 0x15, 0x7f, 0xad, 0x41, 0x39, 0x8c, 0x8f, 0xa2, 0x7b, 0x31, 0xa2, 0xa3, 0x30, - 0x6b, 0xed, 0xfe, 0x78, 0xa6, 0x44, 0x13, 0xb8, 0xfe, 0x33, 0x42, 0xfa, 0x06, 0xe5, 0x14, 0xbe, - 0x47, 0x7f, 0xa2, 0xc1, 0x6c, 0x04, 0xf5, 0x44, 0x71, 0x2a, 0x46, 0x30, 0xd5, 0xda, 0x83, 0x4b, - 0xb8, 0x84, 0x25, 0x8f, 0x98, 0x25, 0x77, 0xf1, 0xad, 0x51, 0x67, 0x78, 0x66, 0x8f, 0x78, 0xb6, - 0xb0, 0xc6, 0x5f, 0x09, 0x0e, 0x51, 0xc6, 0xae, 0x44, 0x08, 0xf2, 0x8c, 0x5d, 0x89, 0x30, 0xbe, - 0x39, 0x6e, 0x25, 0x38, 0x30, 0x49, 0x37, 0xfa, 0xff, 0xa7, 0x21, 0xb7, 0xc1, 0x7f, 0x8c, 0x88, - 0x3c, 0xc8, 0xfb, 0x60, 0x20, 0x5a, 0x8a, 0x03, 0x66, 0x82, 0x8b, 0x43, 0xed, 0x4e, 0x62, 0xbf, - 0x50, 0xff, 0x90, 0xa9, 0x5f, 0xc6, 0x37, 0x7d, 0xf5, 0xe2, 0x47, 0x8f, 0x75, 0x0e, 0x01, 0xd4, - 0x8d, 0x4e, 0x87, 0x4e, 0xfd, 0x8f, 0x35, 0x28, 0xaa, 0x98, 0x1d, 0xba, 0x1b, 0x0b, 0x09, 0xa9, - 0xb0, 0x5f, 0x0d, 0x8f, 0x63, 0x11, 0xfa, 0x1f, 0x33, 0xfd, 0xf7, 0xf0, 0x52, 0x92, 0x7e, 0x87, - 0xf1, 0x87, 0x4d, 0xe0, 0xa8, 0x5b, 0xbc, 0x09, 0x21, 0x50, 0x2f, 0xde, 0x84, 0x30, 0x68, 0x77, - 0xb9, 0x09, 0x03, 0xc6, 0x4f, 0x4d, 0x38, 0x07, 0x08, 0x40, 0x36, 0x14, 0xeb, 0x5c, 0xe5, 0x2a, - 0x15, 0x0d, 0xfe, 0x51, 0x7c, 0x2e, 0x66, 0xeb, 0x45, 0x74, 0x77, 0x4d, 0x97, 0x26, 0x81, 0xb5, - 0x7f, 0xcc, 0x42, 0xe1, 0x95, 0x61, 0x5a, 0x1e, 0xb1, 0x0c, 0xab, 0x4d, 0xd0, 0x09, 0x64, 0x58, - 0xad, 0x8c, 0x66, 0x3c, 0x15, 0x7c, 0x8a, 0x66, 0xbc, 0x10, 0x32, 0x83, 0x1f, 0x30, 0xd5, 0x77, - 0x70, 0xcd, 0x57, 0xdd, 0x0b, 0xe4, 0xd7, 0x19, 0xaa, 0x42, 0xa7, 0x7c, 0x06, 0x59, 0x01, 0xd8, - 0x47, 0xa4, 0x85, 0xd0, 0x96, 0xda, 0xad, 0xf8, 0xce, 0xc4, 0x5d, 0xa6, 0xea, 0x72, 0x19, 0x33, - 0x55, 0xf6, 0x07, 0x00, 0x01, 0x66, 0x18, 0xf5, 0xef, 0x08, 0xc4, 0x58, 0x5b, 0x4e, 0x66, 0x10, - 0x8a, 0x9f, 0x30, 0xc5, 0xf7, 0xf1, 0x9d, 0x58, 0xc5, 0x1d, 0x7f, 0x00, 0x55, 0xde, 0x86, 0xe9, - 0x2d, 0xc3, 0x3d, 0x45, 0x91, 0xea, 0xa7, 0xfc, 0x90, 0xa0, 0x56, 0x8b, 0xeb, 0x12, 0xaa, 0xee, - 0x33, 0x55, 0x4b, 0x78, 0x31, 0x56, 0xd5, 0xa9, 0xe1, 0xd2, 0x62, 0x82, 0x4c, 0xc8, 0xf2, 0x1f, - 0x17, 0x44, 0xdd, 0x19, 0xfa, 0x81, 0x42, 0xd4, 0x9d, 0xe1, 0xdf, 0x23, 0x5c, 0x51, 0xd5, 0x00, - 0x66, 0xe4, 0x93, 0x3e, 0xba, 0x1d, 0x59, 0x9e, 0xf0, 0xf3, 0x7f, 0x6d, 0x29, 0xa9, 0x5b, 0x28, - 0x5c, 0x61, 0x0a, 0x31, 0xbe, 0x1d, 0xbf, 0x7e, 0x82, 0xfd, 0xb9, 0xf6, 0xe4, 0x57, 0x1a, 0xad, - 0x1a, 0x10, 0x60, 0xaf, 0x23, 0x41, 0x12, 0x85, 0x71, 0x47, 0x82, 0x64, 0x04, 0xb6, 0xc5, 0xef, - 0x32, 0xed, 0xcf, 0xf0, 0x4a, 0xac, 0x76, 0xcf, 0x31, 0x2c, 0xf7, 0x0d, 0x71, 0x9e, 0x71, 0x90, - 0xcd, 0x3d, 0x35, 0xfb, 0x34, 0x60, 0xfe, 0xac, 0x02, 0xd3, 0xf4, 0x9c, 0x4a, 0x0b, 0x76, 0x70, - 0xbd, 0x8f, 0x9a, 0x33, 0x02, 0xaa, 0x45, 0xcd, 0x19, 0x45, 0x06, 0x62, 0x0a, 0x36, 0xfb, 0x11, - 0x3a, 0x61, 0x5c, 0xd4, 0xf1, 0x1e, 0x14, 0x14, 0x10, 0x00, 0xc5, 0x48, 0x0c, 0x43, 0x76, 0xd1, - 0x32, 0x11, 0x83, 0x20, 0xe0, 0x65, 0xa6, 0xb4, 0x86, 0xaf, 0x85, 0x95, 0x76, 0x38, 0x1b, 0xd5, - 0xfa, 0x25, 0x14, 0x55, 0xb4, 0x00, 0xc5, 0x08, 0x8d, 0x60, 0x82, 0xd1, 0xec, 0x18, 0x07, 0x36, - 0xc4, 0xa4, 0x09, 0xff, 0x27, 0xf7, 0x92, 0x97, 0x6a, 0xff, 0x1c, 0x72, 0x02, 0x43, 0x88, 0x9b, - 0x6f, 0x18, 0x45, 0x8c, 0x9b, 0x6f, 0x04, 0x80, 0x88, 0x39, 0xfd, 0x31, 0xb5, 0xf4, 0xae, 0x24, - 0x4b, 0x92, 0x50, 0xf9, 0x92, 0x78, 0x49, 0x2a, 0x03, 0x5c, 0x2c, 0x49, 0xa5, 0x72, 0x4f, 0x1d, - 0xab, 0xf2, 0x84, 0x78, 0x22, 0xa4, 0xe4, 0x25, 0x10, 0x25, 0x48, 0x54, 0xf3, 0x3f, 0x1e, 0xc7, - 0x92, 0x78, 0x60, 0x0f, 0xb4, 0x8a, 0xe4, 0x8f, 0xfe, 0x10, 0x20, 0x00, 0x3c, 0xa2, 0x67, 0xb0, - 0x58, 0xd4, 0x34, 0x7a, 0x06, 0x8b, 0xc7, 0x4c, 0x62, 0x12, 0x49, 0xa0, 0x9c, 0x5f, 0x1a, 0xa8, - 0xfa, 0xbf, 0xd4, 0x00, 0x8d, 0x02, 0x24, 0xe8, 0x69, 0xbc, 0x8a, 0x58, 0x40, 0xb6, 0xf6, 0xce, - 0xd5, 0x98, 0x13, 0xeb, 0x45, 0x60, 0x57, 0x9b, 0x0d, 0xe9, 0xbf, 0xa5, 0x96, 0x7d, 0xa3, 0x41, - 0x29, 0x04, 0xb1, 0xa0, 0x87, 0x09, 0xeb, 0x1c, 0x01, 0x75, 0x6b, 0x8f, 0x2e, 0xe5, 0x4b, 0x3c, - 0x9f, 0x29, 0xbb, 0x42, 0x1e, 0xd1, 0xff, 0x54, 0x83, 0x72, 0x18, 0x97, 0x41, 0x09, 0x0a, 0x46, - 0x90, 0xe1, 0xda, 0xca, 0xe5, 0x8c, 0x57, 0x58, 0xad, 0xe0, 0xd4, 0xfe, 0x39, 0xe4, 0x04, 0x9c, - 0x13, 0x17, 0x16, 0x61, 0x60, 0x39, 0x2e, 0x2c, 0x22, 0x58, 0x50, 0x52, 0x58, 0x38, 0x76, 0x97, - 0x28, 0x91, 0x28, 0x40, 0x9f, 0x24, 0x95, 0xe3, 0x23, 0x31, 0x82, 0x18, 0x8d, 0x55, 0x19, 0x44, - 0xa2, 0x84, 0x7c, 0x50, 0x82, 0xc4, 0x4b, 0x22, 0x31, 0x8a, 0x18, 0x25, 0x45, 0x22, 0xd3, 0xaa, - 0x44, 0x62, 0x80, 0xd0, 0xc4, 0x45, 0xe2, 0x08, 0x6c, 0x1e, 0x17, 0x89, 0xa3, 0x20, 0x4f, 0xd2, - 0xda, 0x32, 0xe5, 0xa1, 0x48, 0x9c, 0x8f, 0x41, 0x74, 0xd0, 0x3b, 0x09, 0x3e, 0x8d, 0x85, 0xe4, - 0x6b, 0xcf, 0xae, 0xc8, 0x3d, 0x3e, 0x02, 0xf8, 0x6a, 0xc8, 0x08, 0xf8, 0x5b, 0x0d, 0x16, 0xe2, - 0x20, 0x21, 0x94, 0xa0, 0x2c, 0x01, 0xcf, 0xaf, 0xad, 0x5e, 0x95, 0xfd, 0x0a, 0x7e, 0xf3, 0x63, - 0xe2, 0x45, 0xe5, 0x5f, 0xbe, 0x5f, 0xd2, 0xfe, 0xfd, 0xfb, 0x25, 0xed, 0x3f, 0xbf, 0x5f, 0xd2, - 0xfe, 0xea, 0xbf, 0x96, 0xa6, 0x8e, 0xb3, 0xec, 0x7f, 0x82, 0xbd, 0xfb, 0x9b, 0x00, 0x00, 0x00, - 0xff, 0xff, 0xdd, 0x84, 0xb6, 0xd7, 0x90, 0x36, 0x00, 0x00, + // 3680 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xbc, 0x5b, 0x5f, 0x6f, 0x1b, 0xc7, + 0x76, 0xd7, 0x92, 0x22, 0x29, 0x1e, 0xfe, 0x11, 0x35, 0x92, 0x6d, 0x8a, 0xb6, 0x65, 0x79, 0xfc, + 0x4f, 0xb6, 0x63, 0xf1, 0x5e, 0xe5, 0xb6, 0x0f, 0x6e, 0x11, 0x44, 0x96, 0x18, 0x4b, 0x91, 0x2c, + 0x29, 0x2b, 0x5a, 0x49, 0x81, 0xa0, 0xc4, 0x8a, 0x1c, 0x4b, 0x0b, 0x91, 0xbb, 0xcc, 0xee, 0x92, + 0x96, 0xd2, 0xb4, 0x28, 0x82, 0x04, 0x45, 0x0b, 0xf4, 0xa5, 0x79, 0x68, 0x8b, 0x3e, 0x16, 0x45, + 0x91, 0x97, 0xbe, 0x05, 0xfd, 0x0a, 0x45, 0x5f, 0x5a, 0xa0, 0x5f, 0xa0, 0x48, 0xfb, 0xd2, 0xef, + 0xd0, 0xa2, 0x17, 0xf3, 0x6f, 0x77, 0x76, 0xb9, 0x4b, 0x29, 0x61, 0x92, 0x17, 0x79, 0xe7, 0xcc, + 0x99, 0x73, 0xce, 0x9c, 0x99, 0x73, 0xce, 0xcc, 0x6f, 0x68, 0xc8, 0x3b, 0xfd, 0xf6, 0x6a, 0xdf, + 0xb1, 0x3d, 0x1b, 0x15, 0x89, 0xd7, 0xee, 0xb8, 0xc4, 0x19, 0x12, 0xa7, 0x7f, 0x5c, 0x5b, 0x38, + 0xb1, 0x4f, 0x6c, 0xd6, 0x51, 0xa7, 0x5f, 0x9c, 0xa7, 0xb6, 0x48, 0x79, 0xea, 0xbd, 0x61, 0xbb, + 0xcd, 0xfe, 0xf4, 0x8f, 0xeb, 0x67, 0x43, 0xd1, 0x75, 0x93, 0x75, 0x19, 0x03, 0xef, 0x94, 0xfd, + 0xe9, 0x1f, 0xb3, 0x7f, 0x44, 0xe7, 0xad, 0x13, 0xdb, 0x3e, 0xe9, 0x92, 0xba, 0xd1, 0x37, 0xeb, + 0x86, 0x65, 0xd9, 0x9e, 0xe1, 0x99, 0xb6, 0xe5, 0xf2, 0x5e, 0xfc, 0xb5, 0x06, 0x65, 0x9d, 0xb8, + 0x7d, 0xdb, 0x72, 0xc9, 0x16, 0x31, 0x3a, 0xc4, 0x41, 0xb7, 0x01, 0xda, 0xdd, 0x81, 0xeb, 0x11, + 0xa7, 0x65, 0x76, 0xaa, 0xda, 0xb2, 0xb6, 0x32, 0xad, 0xe7, 0x05, 0x65, 0xbb, 0x83, 0x6e, 0x42, + 0xbe, 0x47, 0x7a, 0xc7, 0xbc, 0x37, 0xc5, 0x7a, 0x67, 0x38, 0x61, 0xbb, 0x83, 0x6a, 0x30, 0xe3, + 0x90, 0xa1, 0xe9, 0x9a, 0xb6, 0x55, 0x4d, 0x2f, 0x6b, 0x2b, 0x69, 0xdd, 0x6f, 0xd3, 0x81, 0x8e, + 0xf1, 0xc6, 0x6b, 0x79, 0xc4, 0xe9, 0x55, 0xa7, 0xf9, 0x40, 0x4a, 0x68, 0x12, 0xa7, 0x87, 0xbf, + 0xca, 0x40, 0x51, 0x37, 0xac, 0x13, 0xa2, 0x93, 0xcf, 0x06, 0xc4, 0xf5, 0x50, 0x05, 0xd2, 0x67, + 0xe4, 0x82, 0xa9, 0x2f, 0xea, 0xf4, 0x93, 0x8f, 0xb7, 0x4e, 0x48, 0x8b, 0x58, 0x5c, 0x71, 0x91, + 0x8e, 0xb7, 0x4e, 0x48, 0xc3, 0xea, 0xa0, 0x05, 0xc8, 0x74, 0xcd, 0x9e, 0xe9, 0x09, 0xad, 0xbc, + 0x11, 0x32, 0x67, 0x3a, 0x62, 0xce, 0x06, 0x80, 0x6b, 0x3b, 0x5e, 0xcb, 0x76, 0x3a, 0xc4, 0xa9, + 0x66, 0x96, 0xb5, 0x95, 0xf2, 0xda, 0xfd, 0x55, 0x75, 0x21, 0x56, 0x55, 0x83, 0x56, 0x0f, 0x6d, + 0xc7, 0xdb, 0xa7, 0xbc, 0x7a, 0xde, 0x95, 0x9f, 0xe8, 0x03, 0x28, 0x30, 0x21, 0x9e, 0xe1, 0x9c, + 0x10, 0xaf, 0x9a, 0x65, 0x52, 0x1e, 0x5c, 0x22, 0xa5, 0xc9, 0x98, 0x75, 0xa6, 0x9e, 0x7f, 0x23, + 0x0c, 0x45, 0x97, 0x38, 0xa6, 0xd1, 0x35, 0x3f, 0x37, 0x8e, 0xbb, 0xa4, 0x9a, 0x5b, 0xd6, 0x56, + 0x66, 0xf4, 0x10, 0x8d, 0xce, 0xff, 0x8c, 0x5c, 0xb8, 0x2d, 0xdb, 0xea, 0x5e, 0x54, 0x67, 0x18, + 0xc3, 0x0c, 0x25, 0xec, 0x5b, 0xdd, 0x0b, 0xb6, 0x68, 0xf6, 0xc0, 0xf2, 0x78, 0x6f, 0x9e, 0xf5, + 0xe6, 0x19, 0x85, 0x75, 0xaf, 0x40, 0xa5, 0x67, 0x5a, 0xad, 0x9e, 0xdd, 0x69, 0xf9, 0x0e, 0x01, + 0xe6, 0x90, 0x72, 0xcf, 0xb4, 0x5e, 0xd9, 0x1d, 0x5d, 0xba, 0x85, 0x72, 0x1a, 0xe7, 0x61, 0xce, + 0x82, 0xe0, 0x34, 0xce, 0x55, 0xce, 0x55, 0x98, 0xa7, 0x32, 0xdb, 0x0e, 0x31, 0x3c, 0x12, 0x30, + 0x17, 0x19, 0xf3, 0x5c, 0xcf, 0xb4, 0x36, 0x58, 0x4f, 0x88, 0xdf, 0x38, 0x1f, 0xe1, 0x2f, 0x09, + 0x7e, 0xe3, 0x3c, 0xcc, 0x8f, 0x57, 0x21, 0xef, 0xfb, 0x1c, 0xcd, 0xc0, 0xf4, 0xde, 0xfe, 0x5e, + 0xa3, 0x32, 0x85, 0x00, 0xb2, 0xeb, 0x87, 0x1b, 0x8d, 0xbd, 0xcd, 0x8a, 0x86, 0x0a, 0x90, 0xdb, + 0x6c, 0xf0, 0x46, 0x0a, 0xbf, 0x00, 0x08, 0xbc, 0x8b, 0x72, 0x90, 0xde, 0x69, 0xfc, 0x41, 0x65, + 0x8a, 0xf2, 0x1c, 0x35, 0xf4, 0xc3, 0xed, 0xfd, 0xbd, 0x8a, 0x46, 0x07, 0x6f, 0xe8, 0x8d, 0xf5, + 0x66, 0xa3, 0x92, 0xa2, 0x1c, 0xaf, 0xf6, 0x37, 0x2b, 0x69, 0x94, 0x87, 0xcc, 0xd1, 0xfa, 0xee, + 0xeb, 0x46, 0x65, 0x1a, 0x7f, 0xa3, 0x41, 0x49, 0xac, 0x17, 0x8f, 0x09, 0xf4, 0x1b, 0xc8, 0x9e, + 0xb2, 0xb8, 0x60, 0x5b, 0xb1, 0xb0, 0x76, 0x2b, 0xb2, 0xb8, 0xa1, 0xd8, 0xd1, 0x05, 0x2f, 0xc2, + 0x90, 0x3e, 0x1b, 0xba, 0xd5, 0xd4, 0x72, 0x7a, 0xa5, 0xb0, 0x56, 0x59, 0xe5, 0x01, 0xbb, 0xba, + 0x43, 0x2e, 0x8e, 0x8c, 0xee, 0x80, 0xe8, 0xb4, 0x13, 0x21, 0x98, 0xee, 0xd9, 0x0e, 0x61, 0x3b, + 0x76, 0x46, 0x67, 0xdf, 0x74, 0x1b, 0xb3, 0x45, 0x13, 0xbb, 0x95, 0x37, 0xf0, 0xb7, 0x1a, 0xc0, + 0xc1, 0xc0, 0x4b, 0x0e, 0x8d, 0x05, 0xc8, 0x0c, 0xa9, 0x60, 0x11, 0x16, 0xbc, 0xc1, 0x62, 0x82, + 0x18, 0x2e, 0xf1, 0x63, 0x82, 0x36, 0xd0, 0x0d, 0xc8, 0xf5, 0x1d, 0x32, 0x6c, 0x9d, 0x0d, 0x99, + 0x92, 0x19, 0x3d, 0x4b, 0x9b, 0x3b, 0x43, 0x74, 0x17, 0x8a, 0xe6, 0x89, 0x65, 0x3b, 0xa4, 0xc5, + 0x65, 0x65, 0x58, 0x6f, 0x81, 0xd3, 0x98, 0xdd, 0x0a, 0x0b, 0x17, 0x9c, 0x55, 0x59, 0x76, 0x29, + 0x09, 0x5b, 0x50, 0x60, 0xa6, 0x4e, 0xe4, 0xbe, 0xc7, 0x81, 0x8d, 0x29, 0x36, 0x6c, 0xd4, 0x85, + 0xc2, 0x6a, 0xfc, 0x29, 0xa0, 0x4d, 0xd2, 0x25, 0x1e, 0x99, 0x24, 0x7b, 0x28, 0x3e, 0x49, 0xab, + 0x3e, 0xc1, 0x7f, 0xa5, 0xc1, 0x7c, 0x48, 0xfc, 0x44, 0xd3, 0xaa, 0x42, 0xae, 0xc3, 0x84, 0x71, + 0x0b, 0xd2, 0xba, 0x6c, 0xa2, 0xa7, 0x30, 0x23, 0x0c, 0x70, 0xab, 0xe9, 0x84, 0x4d, 0x93, 0xe3, + 0x36, 0xb9, 0xf8, 0xdb, 0x14, 0xe4, 0xc5, 0x44, 0xf7, 0xfb, 0x68, 0x1d, 0x4a, 0x0e, 0x6f, 0xb4, + 0xd8, 0x7c, 0x84, 0x45, 0xb5, 0xe4, 0x24, 0xb4, 0x35, 0xa5, 0x17, 0xc5, 0x10, 0x46, 0x46, 0xbf, + 0x07, 0x05, 0x29, 0xa2, 0x3f, 0xf0, 0x84, 0xcb, 0xab, 0x61, 0x01, 0xc1, 0xfe, 0xdb, 0x9a, 0xd2, + 0x41, 0xb0, 0x1f, 0x0c, 0x3c, 0xd4, 0x84, 0x05, 0x39, 0x98, 0xcf, 0x46, 0x98, 0x91, 0x66, 0x52, + 0x96, 0xc3, 0x52, 0x46, 0x97, 0x6a, 0x6b, 0x4a, 0x47, 0x62, 0xbc, 0xd2, 0xa9, 0x9a, 0xe4, 0x9d, + 0xf3, 0xe4, 0x3d, 0x62, 0x52, 0xf3, 0xdc, 0x1a, 0x35, 0xa9, 0x79, 0x6e, 0xbd, 0xc8, 0x43, 0x4e, + 0xb4, 0xf0, 0x3f, 0xa7, 0x00, 0xe4, 0x6a, 0xec, 0xf7, 0xd1, 0x26, 0x94, 0x1d, 0xd1, 0x0a, 0x79, + 0xeb, 0x66, 0xac, 0xb7, 0xc4, 0x22, 0x4e, 0xe9, 0x25, 0x39, 0x88, 0x1b, 0xf7, 0x1e, 0x14, 0x7d, + 0x29, 0x81, 0xc3, 0x16, 0x63, 0x1c, 0xe6, 0x4b, 0x28, 0xc8, 0x01, 0xd4, 0x65, 0x1f, 0xc3, 0x35, + 0x7f, 0x7c, 0x8c, 0xcf, 0xee, 0x8e, 0xf1, 0x99, 0x2f, 0x70, 0x5e, 0x4a, 0x50, 0xbd, 0xa6, 0x1a, + 0x16, 0xb8, 0x6d, 0x31, 0xc6, 0x6d, 0xa3, 0x86, 0x51, 0xc7, 0x01, 0xad, 0x97, 0xbc, 0x89, 0xff, + 0x27, 0x0d, 0xb9, 0x0d, 0xbb, 0xd7, 0x37, 0x1c, 0xba, 0x1a, 0x59, 0x87, 0xb8, 0x83, 0xae, 0xc7, + 0xdc, 0x55, 0x5e, 0xbb, 0x17, 0x96, 0x28, 0xd8, 0xe4, 0xbf, 0x3a, 0x63, 0xd5, 0xc5, 0x10, 0x3a, + 0x58, 0x94, 0xc7, 0xd4, 0x15, 0x06, 0x8b, 0xe2, 0x28, 0x86, 0xc8, 0x40, 0x4e, 0x07, 0x81, 0x5c, + 0x83, 0xdc, 0x90, 0x38, 0x41, 0x49, 0xdf, 0x9a, 0xd2, 0x25, 0x01, 0x3d, 0x86, 0xd9, 0x68, 0x79, + 0xc9, 0x08, 0x9e, 0x72, 0x3b, 0x5c, 0x8d, 0xee, 0x41, 0x31, 0x54, 0xe3, 0xb2, 0x82, 0xaf, 0xd0, + 0x53, 0x4a, 0xdc, 0x75, 0x99, 0x57, 0x69, 0x3d, 0x2e, 0x6e, 0x4d, 0xc9, 0xcc, 0x7a, 0x5d, 0x66, + 0xd6, 0x19, 0x31, 0x4a, 0xe4, 0xd6, 0x50, 0x92, 0x79, 0x3f, 0x9c, 0x64, 0xf0, 0xfb, 0x50, 0x0a, + 0x39, 0x88, 0xd6, 0x9d, 0xc6, 0x47, 0xaf, 0xd7, 0x77, 0x79, 0x91, 0x7a, 0xc9, 0xea, 0x92, 0x5e, + 0xd1, 0x68, 0xad, 0xdb, 0x6d, 0x1c, 0x1e, 0x56, 0x52, 0xa8, 0x04, 0xf9, 0xbd, 0xfd, 0x66, 0x8b, + 0x73, 0xa5, 0xf1, 0x4b, 0x5f, 0x82, 0x28, 0x72, 0x4a, 0x6d, 0x9b, 0x52, 0x6a, 0x9b, 0x26, 0x6b, + 0x5b, 0x2a, 0xa8, 0x6d, 0xac, 0xcc, 0xed, 0x36, 0xd6, 0x0f, 0x1b, 0x95, 0xe9, 0x17, 0x65, 0x28, + 0x72, 0xff, 0xb6, 0x06, 0x16, 0x2d, 0xb5, 0x7f, 0xaf, 0x01, 0x04, 0xd1, 0x84, 0xea, 0x90, 0x6b, + 0x73, 0x3d, 0x55, 0x8d, 0x25, 0xa3, 0x6b, 0xb1, 0x4b, 0xa6, 0x4b, 0x2e, 0xf4, 0x6b, 0xc8, 0xb9, + 0x83, 0x76, 0x9b, 0xb8, 0xb2, 0xe4, 0xdd, 0x88, 0xe6, 0x43, 0x91, 0xad, 0x74, 0xc9, 0x47, 0x87, + 0xbc, 0x31, 0xcc, 0xee, 0x80, 0x15, 0xc0, 0xf1, 0x43, 0x04, 0x1f, 0xfe, 0x5b, 0x0d, 0x0a, 0xca, + 0xe6, 0xfd, 0x91, 0x49, 0xf8, 0x16, 0xe4, 0x99, 0x0d, 0xa4, 0x23, 0xd2, 0xf0, 0x8c, 0x1e, 0x10, + 0xd0, 0xef, 0x42, 0x5e, 0x46, 0x80, 0xcc, 0xc4, 0xd5, 0x78, 0xb1, 0xfb, 0x7d, 0x3d, 0x60, 0xc5, + 0x3b, 0x30, 0xc7, 0xbc, 0xd2, 0xa6, 0x87, 0x6b, 0xe9, 0x47, 0xf5, 0xf8, 0xa9, 0x45, 0x8e, 0x9f, + 0x35, 0x98, 0xe9, 0x9f, 0x5e, 0xb8, 0x66, 0xdb, 0xe8, 0x0a, 0x2b, 0xfc, 0x36, 0xfe, 0x10, 0x90, + 0x2a, 0x6c, 0x92, 0xe9, 0xe2, 0x12, 0x14, 0xb6, 0x0c, 0xf7, 0x54, 0x98, 0x84, 0x9f, 0x42, 0x89, + 0x36, 0x77, 0x8e, 0xae, 0x60, 0x23, 0xbb, 0x1c, 0x48, 0xee, 0x89, 0x7c, 0x8e, 0x60, 0xfa, 0xd4, + 0x70, 0x4f, 0xd9, 0x44, 0x4b, 0x3a, 0xfb, 0x46, 0x8f, 0xa1, 0xd2, 0xe6, 0x93, 0x6c, 0x45, 0xae, + 0x0c, 0xb3, 0x82, 0xee, 0x9f, 0x04, 0x3f, 0x81, 0x22, 0x9f, 0xc3, 0x4f, 0x6d, 0x04, 0x9e, 0x83, + 0xd9, 0x43, 0xcb, 0xe8, 0xbb, 0xa7, 0xb6, 0xac, 0x6e, 0x74, 0xd2, 0x95, 0x80, 0x36, 0x91, 0xc6, + 0x47, 0x30, 0xeb, 0x90, 0x9e, 0x61, 0x5a, 0xa6, 0x75, 0xd2, 0x3a, 0xbe, 0xf0, 0x88, 0x2b, 0x2e, + 0x4c, 0x65, 0x9f, 0xfc, 0x82, 0x52, 0xa9, 0x69, 0xc7, 0x5d, 0xfb, 0x58, 0xa4, 0x39, 0xf6, 0x8d, + 0xbf, 0xd3, 0xa0, 0xf8, 0xb1, 0xe1, 0xb5, 0xe5, 0xd2, 0xa1, 0x6d, 0x28, 0xfb, 0xc9, 0x8d, 0x51, + 0x84, 0x2d, 0x91, 0x12, 0xcb, 0xc6, 0xc8, 0xa3, 0xb4, 0xac, 0x8e, 0xa5, 0xb6, 0x4a, 0x60, 0xa2, + 0x0c, 0xab, 0x4d, 0xba, 0xbe, 0xa8, 0x54, 0xb2, 0x28, 0xc6, 0xa8, 0x8a, 0x52, 0x09, 0x2f, 0x66, + 0x83, 0xe3, 0x07, 0xcf, 0x25, 0xdf, 0xa5, 0x00, 0x8d, 0xda, 0xf0, 0x43, 0x4f, 0x64, 0x0f, 0xa0, + 0xec, 0x7a, 0x86, 0x33, 0xb2, 0x37, 0x4a, 0x8c, 0xea, 0x27, 0xe8, 0x47, 0x30, 0xdb, 0x77, 0xec, + 0x13, 0x87, 0xb8, 0x6e, 0xcb, 0xb2, 0x3d, 0xf3, 0xcd, 0x85, 0x38, 0xd4, 0x96, 0x25, 0x79, 0x8f, + 0x51, 0x51, 0x03, 0x72, 0x6f, 0xcc, 0xae, 0x47, 0x1c, 0xb7, 0x9a, 0x59, 0x4e, 0xaf, 0x94, 0xd7, + 0x9e, 0x5e, 0xe6, 0xb5, 0xd5, 0x0f, 0x18, 0x7f, 0xf3, 0xa2, 0x4f, 0x74, 0x39, 0x56, 0x3d, 0x28, + 0x66, 0x43, 0x87, 0xe7, 0x45, 0x98, 0x79, 0x4b, 0x45, 0xd0, 0x4b, 0x71, 0x8e, 0x9f, 0xed, 0x58, + 0x7b, 0xbb, 0x83, 0x1f, 0x00, 0x04, 0xa2, 0x68, 0x16, 0xde, 0xdb, 0x3f, 0x78, 0xdd, 0xac, 0x4c, + 0xa1, 0x22, 0xcc, 0xec, 0xed, 0x6f, 0x36, 0x76, 0x1b, 0x34, 0x65, 0xe3, 0xba, 0x74, 0x9b, 0xea, + 0xde, 0x90, 0x5c, 0x2d, 0x2c, 0xf7, 0x2f, 0x53, 0x50, 0x12, 0x1b, 0x64, 0xa2, 0x5d, 0xaa, 0xaa, + 0x48, 0x85, 0x54, 0xd0, 0x03, 0x2b, 0xdf, 0x38, 0x1d, 0x71, 0x2e, 0x96, 0x4d, 0x9a, 0x36, 0xf8, + 0x3e, 0x20, 0x1d, 0xe1, 0x71, 0xbf, 0x1d, 0x1b, 0xd9, 0x99, 0xd8, 0xc8, 0x46, 0xf7, 0xa0, 0xe4, + 0x6f, 0x44, 0xc3, 0x15, 0x65, 0x38, 0xaf, 0x17, 0xe5, 0x1e, 0xa3, 0x34, 0xf4, 0x00, 0xb2, 0x64, + 0x48, 0x2c, 0xcf, 0xad, 0x16, 0x58, 0x42, 0x2e, 0xc9, 0xa3, 0x71, 0x83, 0x52, 0x75, 0xd1, 0x89, + 0x7f, 0x07, 0xe6, 0xd8, 0x15, 0xe4, 0xa5, 0x63, 0x58, 0xea, 0x5d, 0xa9, 0xd9, 0xdc, 0x15, 0xae, + 0xa3, 0x9f, 0xa8, 0x0c, 0xa9, 0xed, 0x4d, 0x31, 0xd1, 0xd4, 0xf6, 0x26, 0xfe, 0x52, 0x03, 0xa4, + 0x8e, 0x9b, 0xc8, 0x97, 0x11, 0xe1, 0x52, 0x7d, 0x3a, 0x50, 0xbf, 0x00, 0x19, 0xe2, 0x38, 0xb6, + 0xc3, 0xbc, 0x96, 0xd7, 0x79, 0x03, 0xdf, 0x17, 0x36, 0xe8, 0x64, 0x68, 0x9f, 0xf9, 0x31, 0xc3, + 0xa5, 0x69, 0xbe, 0xa9, 0x3b, 0x30, 0x1f, 0xe2, 0x9a, 0xa8, 0x30, 0x3c, 0x82, 0x6b, 0x4c, 0xd8, + 0x0e, 0x21, 0xfd, 0xf5, 0xae, 0x39, 0x4c, 0xd4, 0xda, 0x87, 0xeb, 0x51, 0xc6, 0x9f, 0xd7, 0x47, + 0xf8, 0xf7, 0x85, 0xc6, 0xa6, 0xd9, 0x23, 0x4d, 0x7b, 0x37, 0xd9, 0x36, 0x9a, 0x38, 0xcf, 0xc8, + 0x85, 0x2b, 0x2a, 0x28, 0xfb, 0xc6, 0xff, 0xa0, 0xc1, 0x8d, 0x91, 0xe1, 0x3f, 0xf3, 0xaa, 0x2e, + 0x01, 0x9c, 0xd0, 0xed, 0x43, 0x3a, 0xb4, 0x83, 0x5f, 0xde, 0x15, 0x8a, 0x6f, 0x27, 0xcd, 0x3d, + 0x45, 0x61, 0xe7, 0x82, 0x58, 0x73, 0xf6, 0xc7, 0x95, 0xe5, 0xe7, 0x36, 0x14, 0x18, 0xe1, 0xd0, + 0x33, 0xbc, 0x81, 0x3b, 0xb2, 0x18, 0x7f, 0x22, 0xb6, 0x80, 0x1c, 0x34, 0xd1, 0xbc, 0x7e, 0x0d, + 0x59, 0x76, 0x6e, 0x95, 0xa7, 0xb6, 0xc8, 0x45, 0x41, 0xb1, 0x43, 0x17, 0x8c, 0xf8, 0x14, 0xb2, + 0xaf, 0x18, 0xd8, 0xa7, 0x58, 0x36, 0x2d, 0x97, 0xc2, 0x32, 0x7a, 0x1c, 0x82, 0xc8, 0xeb, 0xec, + 0x9b, 0x1d, 0x72, 0x08, 0x71, 0x5e, 0xeb, 0xbb, 0xfc, 0x30, 0x95, 0xd7, 0xfd, 0x36, 0x75, 0x59, + 0xbb, 0x6b, 0x12, 0xcb, 0x63, 0xbd, 0xd3, 0xac, 0x57, 0xa1, 0xe0, 0x55, 0xa8, 0x70, 0x4d, 0xeb, + 0x9d, 0x8e, 0x72, 0x58, 0xf1, 0xe5, 0x69, 0x61, 0x79, 0xf8, 0x1f, 0x35, 0x98, 0x53, 0x06, 0x4c, + 0xe4, 0x98, 0x77, 0x20, 0xcb, 0x21, 0x4d, 0x51, 0x17, 0x17, 0xc2, 0xa3, 0xb8, 0x1a, 0x5d, 0xf0, + 0xa0, 0x55, 0xc8, 0xf1, 0x2f, 0x79, 0x62, 0x8c, 0x67, 0x97, 0x4c, 0xf8, 0x01, 0xcc, 0x0b, 0x12, + 0xe9, 0xd9, 0x71, 0x7b, 0x9b, 0x39, 0x14, 0x7f, 0x01, 0x0b, 0x61, 0xb6, 0x89, 0xa6, 0xa4, 0x18, + 0x99, 0xba, 0x8a, 0x91, 0xeb, 0xd2, 0xc8, 0xd7, 0xfd, 0x8e, 0x52, 0xc6, 0xa3, 0xab, 0xae, 0xae, + 0x48, 0x2a, 0xb2, 0x22, 0xfe, 0x04, 0xa4, 0x88, 0x5f, 0x74, 0x02, 0xf3, 0x72, 0x3b, 0xec, 0x9a, + 0xae, 0x7f, 0xb8, 0xfb, 0x1c, 0x90, 0x4a, 0xfc, 0xa5, 0x0d, 0xda, 0x24, 0x6f, 0x1c, 0xe3, 0xa4, + 0x47, 0xfc, 0xfa, 0x44, 0x8f, 0xfa, 0x2a, 0x71, 0xa2, 0x8c, 0x5e, 0x87, 0xb9, 0x57, 0xf6, 0x90, + 0xa6, 0x06, 0x4a, 0x0d, 0x42, 0x86, 0x5f, 0xf5, 0xfc, 0x65, 0xf3, 0xdb, 0x54, 0xb9, 0x3a, 0x60, + 0x22, 0xe5, 0xff, 0xa6, 0x41, 0x71, 0xbd, 0x6b, 0x38, 0x3d, 0xa9, 0xf8, 0x3d, 0xc8, 0xf2, 0x0b, + 0x8c, 0xc0, 0x0c, 0x1e, 0x86, 0xc5, 0xa8, 0xbc, 0xbc, 0xb1, 0xce, 0xaf, 0x3b, 0x62, 0x14, 0x35, + 0x5c, 0x3c, 0x2b, 0x6c, 0x46, 0x9e, 0x19, 0x36, 0xd1, 0x33, 0xc8, 0x18, 0x74, 0x08, 0x4b, 0xc1, + 0xe5, 0xe8, 0xd5, 0x91, 0x49, 0x63, 0xe7, 0x36, 0xce, 0x85, 0x7f, 0x03, 0x05, 0x45, 0x03, 0xbd, + 0x1c, 0xbf, 0x6c, 0x88, 0x03, 0xd8, 0xfa, 0x46, 0x73, 0xfb, 0x88, 0xdf, 0x99, 0xcb, 0x00, 0x9b, + 0x0d, 0xbf, 0x9d, 0xc2, 0x9f, 0x88, 0x51, 0x22, 0xdf, 0xa9, 0xf6, 0x68, 0x49, 0xf6, 0xa4, 0xae, + 0x64, 0xcf, 0x39, 0x94, 0xc4, 0xf4, 0x27, 0x4d, 0xdf, 0x4c, 0x5e, 0x42, 0xfa, 0x56, 0x8c, 0xd7, + 0x05, 0x23, 0x9e, 0x85, 0x92, 0x48, 0xe8, 0x62, 0xff, 0xfd, 0xab, 0x06, 0x65, 0x49, 0x99, 0x14, + 0xdb, 0x94, 0xb0, 0x0c, 0xaf, 0x00, 0x3e, 0x28, 0x73, 0x1d, 0xb2, 0x9d, 0xe3, 0x43, 0xf3, 0x73, + 0x89, 0x43, 0x8b, 0x16, 0xa5, 0x77, 0xb9, 0x1e, 0xfe, 0x18, 0x24, 0x5a, 0xf4, 0x82, 0xee, 0x18, + 0x6f, 0xbc, 0x6d, 0xab, 0x43, 0xce, 0xd9, 0xb9, 0x71, 0x5a, 0x0f, 0x08, 0xec, 0xbe, 0x2a, 0x1e, + 0x8d, 0xd8, 0x61, 0x51, 0x7d, 0x44, 0x9a, 0x87, 0xb9, 0xf5, 0x81, 0x77, 0xda, 0xb0, 0x8c, 0xe3, + 0xae, 0xcc, 0x58, 0xb4, 0xcc, 0x52, 0xe2, 0xa6, 0xe9, 0xaa, 0xd4, 0x06, 0xcc, 0x53, 0x2a, 0xb1, + 0x3c, 0xb3, 0xad, 0xa4, 0x37, 0x59, 0xc4, 0xb4, 0x48, 0x11, 0x33, 0x5c, 0xf7, 0xad, 0xed, 0x74, + 0xc4, 0xd4, 0xfc, 0x36, 0xde, 0xe4, 0xc2, 0x5f, 0xbb, 0xa1, 0x32, 0xf5, 0x43, 0xa5, 0xac, 0x04, + 0x52, 0x5e, 0x12, 0x6f, 0x8c, 0x14, 0xfc, 0x14, 0xae, 0x49, 0x4e, 0x81, 0xfb, 0x8d, 0x61, 0xde, + 0x87, 0xdb, 0x92, 0x79, 0xe3, 0x94, 0x5e, 0xac, 0x0e, 0x84, 0xc2, 0x1f, 0x6b, 0xe7, 0x0b, 0xa8, + 0xfa, 0x76, 0xb2, 0xc3, 0xb2, 0xdd, 0x55, 0x0d, 0x18, 0xb8, 0x62, 0xcf, 0xe4, 0x75, 0xf6, 0x4d, + 0x69, 0x8e, 0xdd, 0xf5, 0x8f, 0x04, 0xf4, 0x1b, 0x6f, 0xc0, 0xa2, 0x94, 0x21, 0x8e, 0xb1, 0x61, + 0x21, 0x23, 0x06, 0xc5, 0x09, 0x11, 0x0e, 0xa3, 0x43, 0xc7, 0xbb, 0x5d, 0xe5, 0x0c, 0xbb, 0x96, + 0xc9, 0xd4, 0x14, 0x99, 0xd7, 0xf8, 0x8e, 0xa0, 0x86, 0xa9, 0x15, 0x43, 0x90, 0xa9, 0x00, 0x95, + 0x2c, 0x16, 0x82, 0x92, 0x47, 0x16, 0x62, 0x44, 0xf4, 0xa7, 0xb0, 0xe4, 0x1b, 0x41, 0xfd, 0x76, + 0x40, 0x9c, 0x9e, 0xe9, 0xba, 0x0a, 0x52, 0x14, 0x37, 0xf1, 0x87, 0x30, 0xdd, 0x27, 0x22, 0xa7, + 0x14, 0xd6, 0xd0, 0x2a, 0x7f, 0xda, 0x5d, 0x55, 0x06, 0xb3, 0x7e, 0xdc, 0x81, 0x3b, 0x52, 0x3a, + 0xf7, 0x68, 0xac, 0xf8, 0xa8, 0x51, 0xf2, 0x42, 0xce, 0xdd, 0x3a, 0x7a, 0x21, 0x4f, 0xf3, 0xb5, + 0xf7, 0xd1, 0xcb, 0x0f, 0xb9, 0x23, 0x65, 0x6c, 0x4d, 0x54, 0x2b, 0x76, 0xb8, 0x4f, 0xfd, 0x90, + 0x9c, 0x48, 0xd8, 0x31, 0x2c, 0x84, 0x23, 0x79, 0xa2, 0x34, 0xb6, 0x00, 0x19, 0xcf, 0x3e, 0x23, + 0x32, 0x89, 0xf1, 0x86, 0x34, 0xd8, 0x0f, 0xf3, 0x89, 0x0c, 0x36, 0x02, 0x61, 0x6c, 0x4b, 0x4e, + 0x6a, 0x2f, 0x5d, 0x4d, 0x79, 0xf8, 0xe2, 0x0d, 0xbc, 0x07, 0xd7, 0xa3, 0x69, 0x62, 0x22, 0x93, + 0x8f, 0xf8, 0x06, 0x8e, 0xcb, 0x24, 0x13, 0xc9, 0xfd, 0x28, 0x48, 0x06, 0x4a, 0x42, 0x99, 0x48, + 0xa4, 0x0e, 0xb5, 0xb8, 0xfc, 0xf2, 0x53, 0xec, 0x57, 0x3f, 0xdd, 0x4c, 0x24, 0xcc, 0x0d, 0x84, + 0x4d, 0xbe, 0xfc, 0x41, 0x8e, 0x48, 0x8f, 0xcd, 0x11, 0x22, 0x48, 0x82, 0x2c, 0xf6, 0x33, 0x6c, + 0x3a, 0xa1, 0x23, 0x48, 0xa0, 0x93, 0xea, 0xa0, 0x35, 0xc4, 0xd7, 0xc1, 0x1a, 0x72, 0x63, 0xab, + 0x69, 0x77, 0xa2, 0xc5, 0xf8, 0x38, 0xc8, 0x9d, 0x23, 0x99, 0x79, 0x22, 0xc1, 0x9f, 0xc0, 0x72, + 0x72, 0x52, 0x9e, 0x44, 0xf2, 0x93, 0x3a, 0xe4, 0xfd, 0x03, 0xa5, 0xf2, 0xb3, 0x88, 0x02, 0xe4, + 0xf6, 0xf6, 0x0f, 0x0f, 0xd6, 0x37, 0x1a, 0xfc, 0x77, 0x11, 0x1b, 0xfb, 0xba, 0xfe, 0xfa, 0xa0, + 0x59, 0x49, 0xad, 0xfd, 0x5f, 0x1a, 0x52, 0x3b, 0x47, 0xe8, 0x0f, 0x21, 0xc3, 0x1f, 0x09, 0xc7, + 0xbc, 0x0c, 0xd7, 0xc6, 0xbd, 0x83, 0xe2, 0x5b, 0x5f, 0xfe, 0xc7, 0x7f, 0x7f, 0x93, 0xba, 0x8e, + 0xe7, 0xea, 0xc3, 0x77, 0x8d, 0x6e, 0xff, 0xd4, 0xa8, 0x9f, 0x0d, 0xeb, 0xac, 0x40, 0x3c, 0xd7, + 0x9e, 0xa0, 0x23, 0x48, 0x1f, 0x0c, 0x3c, 0x94, 0xf8, 0x6c, 0x5c, 0x4b, 0x7e, 0x1f, 0xc5, 0x35, + 0x26, 0x79, 0x01, 0xcf, 0xaa, 0x92, 0xfb, 0x03, 0x8f, 0xca, 0x1d, 0x42, 0x41, 0x7d, 0xe2, 0xbc, + 0xf4, 0x41, 0xb9, 0x76, 0xf9, 0xf3, 0x29, 0xc6, 0x4c, 0xdf, 0x2d, 0x7c, 0x43, 0xd5, 0xc7, 0x5f, + 0x62, 0xd5, 0xf9, 0x34, 0xcf, 0x2d, 0x94, 0xf8, 0xe6, 0x5c, 0x4b, 0x7e, 0x56, 0x8d, 0x9f, 0x8f, + 0x77, 0x6e, 0x51, 0xb9, 0xb6, 0x78, 0x56, 0x6d, 0x7b, 0xe8, 0x4e, 0xcc, 0xb3, 0x9a, 0xfa, 0x80, + 0x54, 0x5b, 0x4e, 0x66, 0x10, 0x9a, 0xee, 0x32, 0x4d, 0x37, 0xf1, 0x75, 0x55, 0x53, 0xdb, 0xe7, + 0x7b, 0xae, 0x3d, 0x59, 0x3b, 0x85, 0x0c, 0x83, 0x89, 0x51, 0x4b, 0x7e, 0xd4, 0x62, 0xb0, 0xef, + 0x84, 0x1d, 0x10, 0x02, 0x98, 0xf1, 0x22, 0xd3, 0x36, 0x8f, 0xcb, 0xbe, 0x36, 0x86, 0x14, 0x3f, + 0xd7, 0x9e, 0xac, 0x68, 0xbf, 0xd2, 0xd6, 0xfe, 0x77, 0x1a, 0x32, 0x0c, 0x34, 0x42, 0x7d, 0x80, + 0x00, 0x53, 0x8d, 0xce, 0x73, 0x04, 0xa5, 0x8d, 0xce, 0x73, 0x14, 0x8e, 0xc5, 0x77, 0x98, 0xe6, + 0x45, 0xbc, 0xe0, 0x6b, 0x66, 0x80, 0x54, 0x9d, 0x61, 0x6c, 0xd4, 0xad, 0x6f, 0x05, 0x6e, 0xc6, + 0xa3, 0x0d, 0xc5, 0x49, 0x0c, 0x81, 0xab, 0xd1, 0x6d, 0x12, 0x03, 0xac, 0xe2, 0x7b, 0x4c, 0xe9, + 0x6d, 0x5c, 0x55, 0x9d, 0xcb, 0xf5, 0x3a, 0x8c, 0x93, 0x2a, 0xfe, 0x4a, 0x83, 0x72, 0x18, 0x1f, + 0x45, 0xf7, 0x62, 0x44, 0x47, 0x61, 0xd6, 0xda, 0xfd, 0xf1, 0x4c, 0x89, 0x26, 0x70, 0xfd, 0x67, + 0x84, 0xf4, 0x0d, 0xca, 0x29, 0x7c, 0x8f, 0xfe, 0x4c, 0x83, 0xd9, 0x08, 0xea, 0x89, 0xe2, 0x54, + 0x8c, 0x60, 0xaa, 0xb5, 0x07, 0x97, 0x70, 0x09, 0x4b, 0x1e, 0x31, 0x4b, 0xee, 0xe2, 0x5b, 0xa3, + 0xce, 0xf0, 0xcc, 0x1e, 0xf1, 0x6c, 0x61, 0x8d, 0xbf, 0x12, 0x1c, 0xa2, 0x8c, 0x5d, 0x89, 0x10, + 0xe4, 0x19, 0xbb, 0x12, 0x61, 0x7c, 0x73, 0xdc, 0x4a, 0x70, 0x60, 0x92, 0x6e, 0xf4, 0xff, 0x4f, + 0x43, 0x6e, 0x83, 0xff, 0x4e, 0x11, 0x79, 0x90, 0xf7, 0xc1, 0x40, 0xb4, 0x14, 0x07, 0xcc, 0x04, + 0x17, 0x87, 0xda, 0x9d, 0xc4, 0x7e, 0xa1, 0xfe, 0x21, 0x53, 0xbf, 0x8c, 0x6f, 0xfa, 0xea, 0xc5, + 0xef, 0x21, 0xeb, 0x1c, 0x02, 0xa8, 0x1b, 0x9d, 0x0e, 0x9d, 0xfa, 0x9f, 0x6a, 0x50, 0x54, 0x31, + 0x3b, 0x74, 0x37, 0x16, 0x12, 0x52, 0x61, 0xbf, 0x1a, 0x1e, 0xc7, 0x22, 0xf4, 0x3f, 0x66, 0xfa, + 0xef, 0xe1, 0xa5, 0x24, 0xfd, 0x0e, 0xe3, 0x0f, 0x9b, 0xc0, 0x51, 0xb7, 0x78, 0x13, 0x42, 0xa0, + 0x5e, 0xbc, 0x09, 0x61, 0xd0, 0xee, 0x72, 0x13, 0x06, 0x8c, 0x9f, 0x9a, 0x70, 0x0e, 0x10, 0x80, + 0x6c, 0x28, 0xd6, 0xb9, 0xca, 0x55, 0x2a, 0x1a, 0xfc, 0xa3, 0xf8, 0x5c, 0xcc, 0xd6, 0x8b, 0xe8, + 0xee, 0x9a, 0x2e, 0x4d, 0x02, 0x6b, 0xff, 0x94, 0x85, 0xc2, 0x2b, 0xc3, 0xb4, 0x3c, 0x62, 0x19, + 0x56, 0x9b, 0xa0, 0x13, 0xc8, 0xb0, 0x5a, 0x19, 0xcd, 0x78, 0x2a, 0xf8, 0x14, 0xcd, 0x78, 0x21, + 0x64, 0x06, 0x3f, 0x60, 0xaa, 0xef, 0xe0, 0x9a, 0xaf, 0xba, 0x17, 0xc8, 0xaf, 0x33, 0x54, 0x85, + 0x4e, 0xf9, 0x0c, 0xb2, 0x02, 0xb0, 0x8f, 0x48, 0x0b, 0xa1, 0x2d, 0xb5, 0x5b, 0xf1, 0x9d, 0x89, + 0xbb, 0x4c, 0xd5, 0xe5, 0x32, 0x66, 0xaa, 0xec, 0x8f, 0x00, 0x02, 0xcc, 0x30, 0xea, 0xdf, 0x11, + 0x88, 0xb1, 0xb6, 0x9c, 0xcc, 0x20, 0x14, 0x3f, 0x61, 0x8a, 0xef, 0xe3, 0x3b, 0xb1, 0x8a, 0x3b, + 0xfe, 0x00, 0xaa, 0xbc, 0x0d, 0xd3, 0x5b, 0x86, 0x7b, 0x8a, 0x22, 0xd5, 0x4f, 0xf9, 0x8d, 0x41, + 0xad, 0x16, 0xd7, 0x25, 0x54, 0xdd, 0x67, 0xaa, 0x96, 0xf0, 0x62, 0xac, 0xaa, 0x53, 0xc3, 0xa5, + 0xc5, 0x04, 0x99, 0x90, 0xe5, 0xbf, 0x3b, 0x88, 0xba, 0x33, 0xf4, 0xdb, 0x85, 0xa8, 0x3b, 0xc3, + 0x3f, 0x55, 0xb8, 0xa2, 0xaa, 0x01, 0xcc, 0xc8, 0xd7, 0x7e, 0x74, 0x3b, 0xb2, 0x3c, 0xe1, 0x5f, + 0x06, 0xd4, 0x96, 0x92, 0xba, 0x85, 0xc2, 0x15, 0xa6, 0x10, 0xe3, 0xdb, 0xf1, 0xeb, 0x27, 0xd8, + 0x9f, 0x6b, 0x4f, 0x7e, 0xa5, 0xd1, 0xaa, 0x01, 0x01, 0xf6, 0x3a, 0x12, 0x24, 0x51, 0x18, 0x77, + 0x24, 0x48, 0x46, 0x60, 0x5b, 0xfc, 0x2e, 0xd3, 0xfe, 0x0c, 0xaf, 0xc4, 0x6a, 0xf7, 0x1c, 0xc3, + 0x72, 0xdf, 0x10, 0xe7, 0x19, 0x07, 0xd9, 0xdc, 0x53, 0xb3, 0x4f, 0x03, 0xe6, 0x2f, 0x2a, 0x30, + 0x4d, 0xcf, 0xa9, 0xb4, 0x60, 0x07, 0xd7, 0xfb, 0xa8, 0x39, 0x23, 0xa0, 0x5a, 0xd4, 0x9c, 0x51, + 0x64, 0x20, 0xa6, 0x60, 0xb3, 0xdf, 0xa7, 0x13, 0xc6, 0x45, 0x1d, 0xef, 0x41, 0x41, 0x01, 0x01, + 0x50, 0x8c, 0xc4, 0x30, 0x64, 0x17, 0x2d, 0x13, 0x31, 0x08, 0x02, 0x5e, 0x66, 0x4a, 0x6b, 0xf8, + 0x5a, 0x58, 0x69, 0x87, 0xb3, 0x51, 0xad, 0x5f, 0x40, 0x51, 0x45, 0x0b, 0x50, 0x8c, 0xd0, 0x08, + 0x26, 0x18, 0xcd, 0x8e, 0x71, 0x60, 0x43, 0x4c, 0x9a, 0xf0, 0x7f, 0x8d, 0x2f, 0x79, 0xa9, 0xf6, + 0xcf, 0x20, 0x27, 0x30, 0x84, 0xb8, 0xf9, 0x86, 0x51, 0xc4, 0xb8, 0xf9, 0x46, 0x00, 0x88, 0x98, + 0xd3, 0x1f, 0x53, 0x4b, 0xef, 0x4a, 0xb2, 0x24, 0x09, 0x95, 0x2f, 0x89, 0x97, 0xa4, 0x32, 0xc0, + 0xc5, 0x92, 0x54, 0x2a, 0xf7, 0xd4, 0xb1, 0x2a, 0x4f, 0x88, 0x27, 0x42, 0x4a, 0x5e, 0x02, 0x51, + 0x82, 0x44, 0x35, 0xff, 0xe3, 0x71, 0x2c, 0x89, 0x07, 0xf6, 0x40, 0xab, 0x48, 0xfe, 0xe8, 0x8f, + 0x01, 0x02, 0xc0, 0x23, 0x7a, 0x06, 0x8b, 0x45, 0x4d, 0xa3, 0x67, 0xb0, 0x78, 0xcc, 0x24, 0x26, + 0x91, 0x04, 0xca, 0xf9, 0xa5, 0x81, 0xaa, 0xff, 0x6b, 0x0d, 0xd0, 0x28, 0x40, 0x82, 0x9e, 0xc6, + 0xab, 0x88, 0x05, 0x64, 0x6b, 0xef, 0x5c, 0x8d, 0x39, 0xb1, 0x5e, 0x04, 0x76, 0xb5, 0xd9, 0x90, + 0xfe, 0x5b, 0x6a, 0xd9, 0xd7, 0x1a, 0x94, 0x42, 0x10, 0x0b, 0x7a, 0x98, 0xb0, 0xce, 0x11, 0x50, + 0xb7, 0xf6, 0xe8, 0x52, 0xbe, 0xc4, 0xf3, 0x99, 0xb2, 0x2b, 0xe4, 0x11, 0xfd, 0xcf, 0x35, 0x28, + 0x87, 0x71, 0x19, 0x94, 0xa0, 0x60, 0x04, 0x19, 0xae, 0xad, 0x5c, 0xce, 0x78, 0x85, 0xd5, 0x0a, + 0x4e, 0xed, 0x9f, 0x41, 0x4e, 0xc0, 0x39, 0x71, 0x61, 0x11, 0x06, 0x96, 0xe3, 0xc2, 0x22, 0x82, + 0x05, 0x25, 0x85, 0x85, 0x63, 0x77, 0x89, 0x12, 0x89, 0x02, 0xf4, 0x49, 0x52, 0x39, 0x3e, 0x12, + 0x23, 0x88, 0xd1, 0x58, 0x95, 0x41, 0x24, 0x4a, 0xc8, 0x07, 0x25, 0x48, 0xbc, 0x24, 0x12, 0xa3, + 0x88, 0x51, 0x52, 0x24, 0x32, 0xad, 0x4a, 0x24, 0x06, 0x08, 0x4d, 0x5c, 0x24, 0x8e, 0xc0, 0xe6, + 0x71, 0x91, 0x38, 0x0a, 0xf2, 0x24, 0xad, 0x2d, 0x53, 0x1e, 0x8a, 0xc4, 0xf9, 0x18, 0x44, 0x07, + 0xbd, 0x93, 0xe0, 0xd3, 0x58, 0x48, 0xbe, 0xf6, 0xec, 0x8a, 0xdc, 0xe3, 0x23, 0x80, 0xaf, 0x86, + 0x8c, 0x80, 0xbf, 0xd3, 0x60, 0x21, 0x0e, 0x12, 0x42, 0x09, 0xca, 0x12, 0xf0, 0xfc, 0xda, 0xea, + 0x55, 0xd9, 0xaf, 0xe0, 0x37, 0x3f, 0x26, 0x5e, 0x54, 0xfe, 0xe5, 0xfb, 0x25, 0xed, 0xdf, 0xbf, + 0x5f, 0xd2, 0xfe, 0xf3, 0xfb, 0x25, 0xed, 0x6f, 0xfe, 0x6b, 0x69, 0xea, 0x38, 0xcb, 0xfe, 0x93, + 0xd8, 0xbb, 0xbf, 0x0d, 0x00, 0x00, 0xff, 0xff, 0xce, 0xbe, 0xdf, 0x21, 0xab, 0x36, 0x00, 0x00, } diff --git a/etcdserver/etcdserverpb/rpc.proto b/etcdserver/etcdserverpb/rpc.proto index 2c18ce101c6b..3368b7adcb8c 100644 --- a/etcdserver/etcdserverpb/rpc.proto +++ b/etcdserver/etcdserverpb/rpc.proto @@ -671,6 +671,13 @@ message WatchCreateRequest { // If prev_kv is set, created watcher gets the previous KV before the event happens. // If the previous KV is already compacted, nothing will be returned. bool prev_kv = 6; + + // If watch_id is provided and non-zero, it will be used to assign to this + // watcher. Since creating a watcher in etcd is not a synchronous operation, + // this can be used ensure that ordering is correct when creating multiple + // watchers on the same stream. Creating a watcher with an ID already in + // use on the stream will cause an error to be returned. + int64 watch_id = 7; } message WatchCancelRequest { diff --git a/mvcc/kv_test.go b/mvcc/kv_test.go index d6f49ee14a97..2d7dc01ff7f0 100644 --- a/mvcc/kv_test.go +++ b/mvcc/kv_test.go @@ -716,7 +716,7 @@ func TestWatchableKVWatch(t *testing.T) { w := s.NewWatchStream() defer w.Close() - wid := w.Watch([]byte("foo"), []byte("fop"), 0) + wid, _ := w.Watch(0, []byte("foo"), []byte("fop"), 0) wev := []mvccpb.Event{ {Type: mvccpb.PUT, @@ -783,7 +783,7 @@ func TestWatchableKVWatch(t *testing.T) { } w = s.NewWatchStream() - wid = w.Watch([]byte("foo1"), []byte("foo2"), 3) + wid, _ = w.Watch(0, []byte("foo1"), []byte("foo2"), 3) select { case resp := <-w.Chan(): diff --git a/mvcc/watchable_store_bench_test.go b/mvcc/watchable_store_bench_test.go index 769d1bc38a83..198fea6bb422 100644 --- a/mvcc/watchable_store_bench_test.go +++ b/mvcc/watchable_store_bench_test.go @@ -78,7 +78,7 @@ func BenchmarkWatchableStoreWatchSyncPut(b *testing.B) { watchIDs := make([]WatchID, b.N) for i := range watchIDs { // non-0 value to keep watchers in unsynced - watchIDs[i] = w.Watch(k, nil, 1) + watchIDs[i], _ = w.Watch(0, k, nil, 1) } b.ResetTimer() @@ -142,7 +142,7 @@ func BenchmarkWatchableStoreUnsyncedCancel(b *testing.B) { watchIDs := make([]WatchID, watcherN) for i := 0; i < watcherN; i++ { // non-0 value to keep watchers in unsynced - watchIDs[i] = w.Watch(testKey, nil, 1) + watchIDs[i], _ = w.Watch(0, testKey, nil, 1) } // random-cancel N watchers to make it not biased towards @@ -182,7 +182,7 @@ func BenchmarkWatchableStoreSyncedCancel(b *testing.B) { watchIDs := make([]WatchID, watcherN) for i := 0; i < watcherN; i++ { // 0 for startRev to keep watchers in synced - watchIDs[i] = w.Watch(testKey, nil, 0) + watchIDs[i], _ = w.Watch(0, testKey, nil, 0) } // randomly cancel watchers to make it not biased towards diff --git a/mvcc/watchable_store_test.go b/mvcc/watchable_store_test.go index 52e1b90c0c00..c36a541a5f3d 100644 --- a/mvcc/watchable_store_test.go +++ b/mvcc/watchable_store_test.go @@ -42,7 +42,7 @@ func TestWatch(t *testing.T) { s.Put(testKey, testValue, lease.NoLease) w := s.NewWatchStream() - w.Watch(testKey, nil, 0) + w.Watch(0, testKey, nil, 0) if !s.synced.contains(string(testKey)) { // the key must have had an entry in synced @@ -63,7 +63,7 @@ func TestNewWatcherCancel(t *testing.T) { s.Put(testKey, testValue, lease.NoLease) w := s.NewWatchStream() - wt := w.Watch(testKey, nil, 0) + wt, _ := w.Watch(0, testKey, nil, 0) if err := w.Cancel(wt); err != nil { t.Error(err) @@ -114,7 +114,7 @@ func TestCancelUnsynced(t *testing.T) { watchIDs := make([]WatchID, watcherN) for i := 0; i < watcherN; i++ { // use 1 to keep watchers in unsynced - watchIDs[i] = w.Watch(testKey, nil, 1) + watchIDs[i], _ = w.Watch(0, testKey, nil, 1) } for _, idx := range watchIDs { @@ -160,7 +160,7 @@ func TestSyncWatchers(t *testing.T) { for i := 0; i < watcherN; i++ { // specify rev as 1 to keep watchers in unsynced - w.Watch(testKey, nil, 1) + w.Watch(0, testKey, nil, 1) } // Before running s.syncWatchers() synced should be empty because we manually @@ -242,7 +242,7 @@ func TestWatchCompacted(t *testing.T) { } w := s.NewWatchStream() - wt := w.Watch(testKey, nil, compactRev-1) + wt, _ := w.Watch(0, testKey, nil, compactRev-1) select { case resp := <-w.Chan(): @@ -271,7 +271,7 @@ func TestWatchFutureRev(t *testing.T) { w := s.NewWatchStream() wrev := int64(10) - w.Watch(testKey, nil, wrev) + w.Watch(0, testKey, nil, wrev) for i := 0; i < 10; i++ { rev := s.Put(testKey, testValue, lease.NoLease) @@ -310,7 +310,7 @@ func TestWatchRestore(t *testing.T) { defer cleanup(newStore, newBackend, newPath) w := newStore.NewWatchStream() - w.Watch(testKey, nil, rev-1) + w.Watch(0, testKey, nil, rev-1) newStore.Restore(b) select { @@ -349,7 +349,7 @@ func TestWatchBatchUnsynced(t *testing.T) { } w := s.NewWatchStream() - w.Watch(v, nil, 1) + w.Watch(0, v, nil, 1) for i := 0; i < batches; i++ { if resp := <-w.Chan(); len(resp.Events) != watchBatchMaxRevs { t.Fatalf("len(events) = %d, want %d", len(resp.Events), watchBatchMaxRevs) @@ -485,7 +485,7 @@ func TestWatchVictims(t *testing.T) { for i := 0; i < numWatches; i++ { go func() { w := s.NewWatchStream() - w.Watch(testKey, nil, 1) + w.Watch(0, testKey, nil, 1) defer func() { w.Close() wg.Done() @@ -561,7 +561,7 @@ func TestStressWatchCancelClose(t *testing.T) { w := s.NewWatchStream() ids := make([]WatchID, 10) for i := range ids { - ids[i] = w.Watch(testKey, nil, 0) + ids[i], _ = w.Watch(0, testKey, nil, 0) } <-readyc wg.Add(1 + len(ids)/2) diff --git a/mvcc/watcher.go b/mvcc/watcher.go index bc0c6322fd1f..469ab22bcc8f 100644 --- a/mvcc/watcher.go +++ b/mvcc/watcher.go @@ -22,8 +22,14 @@ import ( "github.com/coreos/etcd/mvcc/mvccpb" ) +// DefaultWatchID is the watcher ID passed in WatchStream.Watch when no +// user-provided ID is available. If pass, an ID will automatically be assigned. +const DefaultWatchID WatchID = 0 + var ( - ErrWatcherNotExist = errors.New("mvcc: watcher does not exist") + ErrWatcherNotExist = errors.New("mvcc: watcher does not exist") + ErrEmptyWatcherRange = errors.New("mvcc: watcher range is empty") + ErrWatcherDuplicateID = errors.New("mvcc: duplicate watch ID provided on the WatchStream") ) type WatchID int64 @@ -33,7 +39,9 @@ type FilterFunc func(e mvccpb.Event) bool type WatchStream interface { // Watch creates a watcher. The watcher watches the events happening or - // happened on the given key or range [key, end) from the given startRev. + // happened on the given key or range [key, end) from the given startRev. If + // the ID is not equal to DefaultWatchID, it will be used, otherwise a new + // ID will be returned. // // The whole event history can be watched unless compacted. // If `startRev` <=0, watch observes events after currentRev. @@ -41,7 +49,7 @@ type WatchStream interface { // The returned `id` is the ID of this watcher. It appears as WatchID // in events that are sent to the created watcher through stream channel. // - Watch(key, end []byte, startRev int64, fcs ...FilterFunc) WatchID + Watch(id WatchID, key, end []byte, startRev int64, fcs ...FilterFunc) (WatchID, error) // Chan returns a chan. All watch response will be sent to the returned chan. Chan() <-chan WatchResponse @@ -99,27 +107,34 @@ type watchStream struct { // Watch creates a new watcher in the stream and returns its WatchID. // TODO: return error if ws is closed? -func (ws *watchStream) Watch(key, end []byte, startRev int64, fcs ...FilterFunc) WatchID { +func (ws *watchStream) Watch(id WatchID, key, end []byte, startRev int64, fcs ...FilterFunc) (WatchID, error) { // prevent wrong range where key >= end lexicographically // watch request with 'WithFromKey' has empty-byte range end if len(end) != 0 && bytes.Compare(key, end) != -1 { - return -1 + return -1, ErrEmptyWatcherRange } ws.mu.Lock() defer ws.mu.Unlock() if ws.closed { - return -1 + return -1, ErrEmptyWatcherRange } - id := ws.nextID - ws.nextID++ + if id == DefaultWatchID { + for ws.watchers[ws.nextID] != nil { + ws.nextID++ + } + id = ws.nextID + ws.nextID++ + } else if ws.watchers[id] != nil { + return -1, ErrWatcherDuplicateID + } w, c := ws.watchable.watch(key, end, startRev, id, ws.ch, fcs...) ws.cancels[id] = c ws.watchers[id] = w - return id + return id, nil } func (ws *watchStream) Chan() <-chan WatchResponse { diff --git a/mvcc/watcher_bench_test.go b/mvcc/watcher_bench_test.go index 8a4242f3f20f..86cbea7df2e7 100644 --- a/mvcc/watcher_bench_test.go +++ b/mvcc/watcher_bench_test.go @@ -33,6 +33,6 @@ func BenchmarkKVWatcherMemoryUsage(b *testing.B) { b.ReportAllocs() b.StartTimer() for i := 0; i < b.N; i++ { - w.Watch([]byte(fmt.Sprint("foo", i)), nil, 0) + w.Watch(0, []byte(fmt.Sprint("foo", i)), nil, 0) } } diff --git a/mvcc/watcher_test.go b/mvcc/watcher_test.go index 3d259d1f160a..f08e7db099b2 100644 --- a/mvcc/watcher_test.go +++ b/mvcc/watcher_test.go @@ -40,7 +40,7 @@ func TestWatcherWatchID(t *testing.T) { idm := make(map[WatchID]struct{}) for i := 0; i < 10; i++ { - id := w.Watch([]byte("foo"), nil, 0) + id, _ := w.Watch(0, []byte("foo"), nil, 0) if _, ok := idm[id]; ok { t.Errorf("#%d: id %d exists", i, id) } @@ -62,7 +62,7 @@ func TestWatcherWatchID(t *testing.T) { // unsynced watchers for i := 10; i < 20; i++ { - id := w.Watch([]byte("foo2"), nil, 1) + id, _ := w.Watch(0, []byte("foo2"), nil, 1) if _, ok := idm[id]; ok { t.Errorf("#%d: id %d exists", i, id) } @@ -79,6 +79,41 @@ func TestWatcherWatchID(t *testing.T) { } } +func TestWatcherRequestsCustomID(t *testing.T) { + b, tmpPath := backend.NewDefaultTmpBackend() + s := WatchableKV(newWatchableStore(b, &lease.FakeLessor{}, nil)) + defer cleanup(s, b, tmpPath) + + w := s.NewWatchStream() + defer w.Close() + + // - Request specifically ID #1 + // - Try to duplicate it, get an error + // - Make sure the auto-assignment skips over things we manually assigned + + tt := []struct { + GivenID WatchID + ExpectedID WatchID + ExpectedErr error + }{ + {1, 1, nil}, + {1, 0, ErrWatcherDuplicateID}, + {0, 0, nil}, + {0, 2, nil}, + } + + for i, tcase := range tt { + id, err := w.Watch(tcase.GivenID, []byte("foo"), nil, 0) + if tcase.ExpectedErr != nil || err != nil { + if err != tcase.ExpectedErr { + t.Errorf("expected get error %q in test case %q, got %q", tcase.ExpectedErr, i, err) + } + } else if tcase.ExpectedID != id { + t.Errorf("expected to create ID %d, got %d in test case %d", tcase.ExpectedID, id, i) + } + } +} + // TestWatcherWatchPrefix tests if Watch operation correctly watches // and returns events with matching prefixes. func TestWatcherWatchPrefix(t *testing.T) { @@ -95,7 +130,7 @@ func TestWatcherWatchPrefix(t *testing.T) { keyWatch, keyEnd, keyPut := []byte("foo"), []byte("fop"), []byte("foobar") for i := 0; i < 10; i++ { - id := w.Watch(keyWatch, keyEnd, 0) + id, _ := w.Watch(0, keyWatch, keyEnd, 0) if _, ok := idm[id]; ok { t.Errorf("#%d: unexpected duplicated id %x", i, id) } @@ -127,7 +162,7 @@ func TestWatcherWatchPrefix(t *testing.T) { // unsynced watchers for i := 10; i < 15; i++ { - id := w.Watch(keyWatch1, keyEnd1, 1) + id, _ := w.Watch(0, keyWatch1, keyEnd1, 1) if _, ok := idm[id]; ok { t.Errorf("#%d: id %d exists", i, id) } @@ -163,14 +198,14 @@ func TestWatcherWatchWrongRange(t *testing.T) { w := s.NewWatchStream() defer w.Close() - if id := w.Watch([]byte("foa"), []byte("foa"), 1); id != -1 { - t.Fatalf("key == end range given; id expected -1, got %d", id) + if _, err := w.Watch(0, []byte("foa"), []byte("foa"), 1); err != ErrEmptyWatcherRange { + t.Fatalf("key == end range given; expected ErrEmptyWatcherRange, got %+v", err) } - if id := w.Watch([]byte("fob"), []byte("foa"), 1); id != -1 { - t.Fatalf("key > end range given; id expected -1, got %d", id) + if _, err := w.Watch(0, []byte("fob"), []byte("foa"), 1); err != ErrEmptyWatcherRange { + t.Fatalf("key > end range given; expected ErrEmptyWatcherRange, got %+v", err) } // watch request with 'WithFromKey' has empty-byte range end - if id := w.Watch([]byte("foo"), []byte{}, 1); id != 0 { + if id, _ := w.Watch(0, []byte("foo"), []byte{}, 1); id != 0 { t.Fatalf("\x00 is range given; id expected 0, got %d", id) } } @@ -192,7 +227,7 @@ func TestWatchDeleteRange(t *testing.T) { w := s.NewWatchStream() from, to := []byte(testKeyPrefix), []byte(fmt.Sprintf("%s_%d", testKeyPrefix, 99)) - w.Watch(from, to, 0) + w.Watch(0, from, to, 0) s.DeleteRange(from, to) @@ -222,7 +257,7 @@ func TestWatchStreamCancelWatcherByID(t *testing.T) { w := s.NewWatchStream() defer w.Close() - id := w.Watch([]byte("foo"), nil, 0) + id, _ := w.Watch(0, []byte("foo"), nil, 0) tests := []struct { cancelID WatchID @@ -284,7 +319,7 @@ func TestWatcherRequestProgress(t *testing.T) { default: } - id := w.Watch(notTestKey, nil, 1) + id, _ := w.Watch(0, notTestKey, nil, 1) w.RequestProgress(id) select { case resp := <-w.Chan(): @@ -295,7 +330,7 @@ func TestWatcherRequestProgress(t *testing.T) { s.syncWatchers() w.RequestProgress(id) - wrs := WatchResponse{WatchID: 0, Revision: 2} + wrs := WatchResponse{WatchID: id, Revision: 2} select { case resp := <-w.Chan(): if !reflect.DeepEqual(resp, wrs) { @@ -318,7 +353,7 @@ func TestWatcherWatchWithFilter(t *testing.T) { return e.Type == mvccpb.PUT } - w.Watch([]byte("foo"), nil, 0, filterPut) + w.Watch(0, []byte("foo"), nil, 0, filterPut) done := make(chan struct{}) go func() {