diff --git a/Documentation/dev-guide/api_reference_v3.md b/Documentation/dev-guide/api_reference_v3.md index b99797e56a5..578724654c6 100644 --- a/Documentation/dev-guide/api_reference_v3.md +++ b/Documentation/dev-guide/api_reference_v3.md @@ -401,6 +401,7 @@ CompactionRequest compacts the key-value store up to a given revision. All super | create_revision | create_revision is the creation revision of the given key | int64 | | mod_revision | mod_revision is the last modified revision of the given key. | int64 | | value | value is the value of the given key, in bytes. | bytes | +| range_end | range_end compares the given target to all keys in the range [key, range_end). See RangeRequest for more details on key ranges. | bytes | diff --git a/Documentation/dev-guide/apispec/swagger/rpc.swagger.json b/Documentation/dev-guide/apispec/swagger/rpc.swagger.json index 6ab62a0d2c7..ed487f991a3 100644 --- a/Documentation/dev-guide/apispec/swagger/rpc.swagger.json +++ b/Documentation/dev-guide/apispec/swagger/rpc.swagger.json @@ -1449,6 +1449,11 @@ "type": "string", "format": "int64" }, + "range_end": { + "description": "range_end compares the given target to all keys in the range [key, range_end).\nSee RangeRequest for more details on key ranges.", + "type": "string", + "format": "byte" + }, "result": { "description": "result is logical comparison operation for this comparison.", "$ref": "#/definitions/CompareCompareResult" @@ -2256,4 +2261,4 @@ "ApiKey": [] } ] -} +} \ No newline at end of file diff --git a/clientv3/compare.go b/clientv3/compare.go index c55228cc0b8..e01489c06fd 100644 --- a/clientv3/compare.go +++ b/clientv3/compare.go @@ -99,6 +99,18 @@ func (cmp *Cmp) ValueBytes() []byte { // WithValueBytes sets the byte slice for the comparison's value. func (cmp *Cmp) WithValueBytes(v []byte) { cmp.TargetUnion.(*pb.Compare_Value).Value = v } +// WithRange sets the comparison to scan the range [key, end). +func (cmp Cmp) WithRange(end string) Cmp { + cmp.RangeEnd = []byte(end) + return cmp +} + +// WithPrefix sets the comparison to scan all keys prefixed by the key. +func (cmp Cmp) WithPrefix() Cmp { + cmp.RangeEnd = getPrefix(cmp.Key) + return cmp +} + func mustInt64(val interface{}) int64 { if v, ok := val.(int64); ok { return v diff --git a/clientv3/integration/txn_test.go b/clientv3/integration/txn_test.go index 064be976dd9..cbfc59e6716 100644 --- a/clientv3/integration/txn_test.go +++ b/clientv3/integration/txn_test.go @@ -152,3 +152,30 @@ func TestTxnSuccess(t *testing.T) { t.Fatalf("unexpected Get response %v", resp) } } + +func TestTxnCompareRange(t *testing.T) { + defer testutil.AfterTest(t) + + clus := integration.NewClusterV3(t, &integration.ClusterConfig{Size: 1}) + defer clus.Terminate(t) + + kv := clus.Client(0) + fooResp, err := kv.Put(context.TODO(), "foo/", "bar") + if err != nil { + t.Fatal(err) + } + if _, err = kv.Put(context.TODO(), "foo/a", "baz"); err != nil { + t.Fatal(err) + } + tresp, terr := kv.Txn(context.TODO()).If( + clientv3.Compare( + clientv3.CreateRevision("foo/"), "=", fooResp.Header.Revision). + WithPrefix(), + ).Commit() + if terr != nil { + t.Fatal(terr) + } + if tresp.Succeeded { + t.Fatal("expected prefix compare to false, got compares as true") + } +} diff --git a/clientv3/namespace/kv.go b/clientv3/namespace/kv.go index f3e82d6b89a..dc013742b01 100644 --- a/clientv3/namespace/kv.go +++ b/clientv3/namespace/kv.go @@ -105,8 +105,11 @@ func (txn *txnPrefix) If(cs ...clientv3.Cmp) clientv3.Txn { newCmps := make([]clientv3.Cmp, len(cs)) for i := range cs { newCmps[i] = cs[i] - pfxKey, _ := txn.kv.prefixInterval(cs[i].KeyBytes(), nil) + pfxKey, endKey := txn.kv.prefixInterval(cs[i].KeyBytes(), cs[i].RangeEnd) newCmps[i].WithKeyBytes(pfxKey) + if len(cs[i].RangeEnd) != 0 { + newCmps[i].RangeEnd = endKey + } } txn.Txn = txn.Txn.If(newCmps...) return txn diff --git a/etcdserver/apply.go b/etcdserver/apply.go index 949f36ca775..707ac89f0a0 100644 --- a/etcdserver/apply.go +++ b/etcdserver/apply.go @@ -194,18 +194,15 @@ func (a *applierV3backend) Put(txn mvcc.TxnWrite, p *pb.PutRequest) (resp *pb.Pu func (a *applierV3backend) DeleteRange(txn mvcc.TxnWrite, dr *pb.DeleteRangeRequest) (*pb.DeleteRangeResponse, error) { resp := &pb.DeleteRangeResponse{} resp.Header = &pb.ResponseHeader{} + end := mkGteRange(dr.RangeEnd) if txn == nil { txn = a.s.kv.Write() defer txn.End() } - if isGteRange(dr.RangeEnd) { - dr.RangeEnd = []byte{} - } - if dr.PrevKv { - rr, err := txn.Range(dr.Key, dr.RangeEnd, mvcc.RangeOptions{}) + rr, err := txn.Range(dr.Key, end, mvcc.RangeOptions{}) if err != nil { return nil, err } @@ -216,7 +213,7 @@ func (a *applierV3backend) DeleteRange(txn mvcc.TxnWrite, dr *pb.DeleteRangeRequ } } - resp.Deleted, resp.Header.Revision = txn.DeleteRange(dr.Key, dr.RangeEnd) + resp.Deleted, resp.Header.Revision = txn.DeleteRange(dr.Key, end) return resp, nil } @@ -229,10 +226,6 @@ func (a *applierV3backend) Range(txn mvcc.TxnRead, r *pb.RangeRequest) (*pb.Rang defer txn.End() } - if isGteRange(r.RangeEnd) { - r.RangeEnd = []byte{} - } - limit := r.Limit if r.SortOrder != pb.RangeRequest_NONE || r.MinModRevision != 0 || r.MaxModRevision != 0 || @@ -251,7 +244,7 @@ func (a *applierV3backend) Range(txn mvcc.TxnRead, r *pb.RangeRequest) (*pb.Rang Count: r.CountOnly, } - rr, err := txn.Range(r.Key, r.RangeEnd, ro) + rr, err := txn.Range(r.Key, mkGteRange(r.RangeEnd), ro) if err != nil { return nil, err } @@ -374,50 +367,57 @@ func (a *applierV3backend) compareToOps(rv mvcc.ReadView, rt *pb.TxnRequest) ([] // applyCompare applies the compare request. // If the comparison succeeds, it returns true. Otherwise, returns false. func applyCompare(rv mvcc.ReadView, c *pb.Compare) bool { - rr, err := rv.Range(c.Key, nil, mvcc.RangeOptions{}) + // TOOD: possible optimizations + // * chunk reads for large ranges to conserve memory + // * rewrite rules for common patterns: + // ex. "[a, b) createrev > 0" => "limit 1 /\ kvs > 0" + // * caching + rr, err := rv.Range(c.Key, mkGteRange(c.RangeEnd), mvcc.RangeOptions{}) if err != nil { return false } - var ckv mvccpb.KeyValue - if len(rr.KVs) != 0 { - ckv = rr.KVs[0] - } else { - // Use the zero value of ckv normally. However... + if len(rr.KVs) == 0 { if c.Target == pb.Compare_VALUE { - // Always fail if we're comparing a value on a key that doesn't exist. - // We can treat non-existence as the empty set explicitly, such that - // even a key with a value of length 0 bytes is still a real key - // that was written that way + // Always fail if comparing a value on a key/keys that doesn't exist; + // nil == empty string in grpc; no way to represent missing value + return false + } + return compareKV(c, mvccpb.KeyValue{}) + } + for _, kv := range rr.KVs { + if !compareKV(c, kv) { return false } } + return true +} - // -1 is less, 0 is equal, 1 is greater +func compareKV(c *pb.Compare, ckv mvccpb.KeyValue) bool { var result int + rev := int64(0) switch c.Target { case pb.Compare_VALUE: - tv, _ := c.TargetUnion.(*pb.Compare_Value) - if tv != nil { - result = bytes.Compare(ckv.Value, tv.Value) + v := []byte{} + if tv, _ := c.TargetUnion.(*pb.Compare_Value); tv != nil { + v = tv.Value } + result = bytes.Compare(ckv.Value, v) case pb.Compare_CREATE: - tv, _ := c.TargetUnion.(*pb.Compare_CreateRevision) - if tv != nil { - result = compareInt64(ckv.CreateRevision, tv.CreateRevision) + if tv, _ := c.TargetUnion.(*pb.Compare_CreateRevision); tv != nil { + rev = tv.CreateRevision } - + result = compareInt64(ckv.CreateRevision, rev) case pb.Compare_MOD: - tv, _ := c.TargetUnion.(*pb.Compare_ModRevision) - if tv != nil { - result = compareInt64(ckv.ModRevision, tv.ModRevision) + if tv, _ := c.TargetUnion.(*pb.Compare_ModRevision); tv != nil { + rev = tv.ModRevision } + result = compareInt64(ckv.ModRevision, rev) case pb.Compare_VERSION: - tv, _ := c.TargetUnion.(*pb.Compare_Version) - if tv != nil { - result = compareInt64(ckv.Version, tv.Version) + if tv, _ := c.TargetUnion.(*pb.Compare_Version); tv != nil { + rev = tv.Version } + result = compareInt64(ckv.Version, rev) } - switch c.Result { case pb.Compare_EQUAL: return result == 0 @@ -830,10 +830,15 @@ func compareInt64(a, b int64) int { } } -// isGteRange determines if the range end is a >= range. This works around grpc +// mkGteRange determines if the range end is a >= range. This works around grpc // sending empty byte strings as nil; >= is encoded in the range end as '\0'. -func isGteRange(rangeEnd []byte) bool { - return len(rangeEnd) == 1 && rangeEnd[0] == 0 +// If it is a GTE range, then []byte{} is returned to indicate the empty byte +// string (vs nil being no byte string). +func mkGteRange(rangeEnd []byte) []byte { + if len(rangeEnd) == 1 && rangeEnd[0] == 0 { + return []byte{} + } + return rangeEnd } func noSideEffect(r *pb.InternalRaftRequest) bool { diff --git a/etcdserver/apply_auth.go b/etcdserver/apply_auth.go index 5cd74018dac..d4d881ab045 100644 --- a/etcdserver/apply_auth.go +++ b/etcdserver/apply_auth.go @@ -149,7 +149,7 @@ func checkTxnReqsPermission(as auth.AuthStore, ai *auth.AuthInfo, reqs []*pb.Req func checkTxnAuth(as auth.AuthStore, ai *auth.AuthInfo, rt *pb.TxnRequest) error { for _, c := range rt.Compare { - if err := as.IsRangePermitted(ai, c.Key, nil); err != nil { + if err := as.IsRangePermitted(ai, c.Key, c.RangeEnd); err != nil { return err } } diff --git a/etcdserver/etcdserverpb/rpc.pb.go b/etcdserver/etcdserverpb/rpc.pb.go index 073d4a39468..8d56f556dac 100644 --- a/etcdserver/etcdserverpb/rpc.pb.go +++ b/etcdserver/etcdserverpb/rpc.pb.go @@ -926,6 +926,9 @@ type Compare struct { // *Compare_ModRevision // *Compare_Value TargetUnion isCompare_TargetUnion `protobuf_oneof:"target_union"` + // range_end compares the given target to all keys in the range [key, range_end). + // See RangeRequest for more details on key ranges. + RangeEnd []byte `protobuf:"bytes,8,opt,name=range_end,json=rangeEnd,proto3" json:"range_end,omitempty"` } func (m *Compare) Reset() { *m = Compare{} } @@ -1013,6 +1016,13 @@ func (m *Compare) GetValue() []byte { return nil } +func (m *Compare) GetRangeEnd() []byte { + if m != nil { + return m.RangeEnd + } + return nil +} + // XXX_OneofFuncs is for the internal use of the proto package. func (*Compare) XXX_OneofFuncs() (func(msg proto.Message, b *proto.Buffer) error, func(msg proto.Message, tag, wire int, b *proto.Buffer) (bool, error), func(msg proto.Message) (n int), []interface{}) { return _Compare_OneofMarshaler, _Compare_OneofUnmarshaler, _Compare_OneofSizer, []interface{}{ @@ -5037,6 +5047,12 @@ func (m *Compare) MarshalTo(dAtA []byte) (int, error) { } i += nn13 } + if len(m.RangeEnd) > 0 { + dAtA[i] = 0x42 + i++ + i = encodeVarintRpc(dAtA, i, uint64(len(m.RangeEnd))) + i += copy(dAtA[i:], m.RangeEnd) + } return i, nil } @@ -7597,6 +7613,10 @@ func (m *Compare) Size() (n int) { if m.TargetUnion != nil { n += m.TargetUnion.Size() } + l = len(m.RangeEnd) + if l > 0 { + n += 1 + l + sovRpc(uint64(l)) + } return n } @@ -10203,6 +10223,37 @@ func (m *Compare) Unmarshal(dAtA []byte) error { copy(v, dAtA[iNdEx:postIndex]) m.TargetUnion = &Compare_Value{v} iNdEx = postIndex + case 8: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field RangeEnd", 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.RangeEnd = append(m.RangeEnd[:0], dAtA[iNdEx:postIndex]...) + if m.RangeEnd == nil { + m.RangeEnd = []byte{} + } + iNdEx = postIndex default: iNdEx = preIndex skippy, err := skipRpc(dAtA[iNdEx:]) @@ -17071,221 +17122,222 @@ var ( func init() { proto.RegisterFile("rpc.proto", fileDescriptorRpc) } var fileDescriptorRpc = []byte{ - // 3450 bytes of a gzipped FileDescriptorProto + // 3459 bytes of a gzipped FileDescriptorProto 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xbc, 0x3b, 0x5b, 0x6f, 0x1b, 0xc7, - 0xb9, 0x5a, 0x5e, 0xc5, 0x8f, 0x17, 0xd1, 0x23, 0xd9, 0xa6, 0x68, 0x5b, 0x96, 0xc7, 0x37, 0xd9, - 0x4e, 0xa4, 0x44, 0xc9, 0x39, 0x0f, 0x3e, 0x41, 0x70, 0x64, 0x89, 0xb1, 0x74, 0x24, 0x4b, 0xce, - 0x4a, 0x76, 0x72, 0x80, 0xa0, 0xc4, 0x8a, 0x1c, 0x53, 0x0b, 0x91, 0xbb, 0xcc, 0xee, 0x92, 0x96, - 0xd2, 0x14, 0x28, 0xd2, 0x04, 0x45, 0x0b, 0xf4, 0xa5, 0x79, 0xe8, 0xed, 0xb1, 0x28, 0x8a, 0xfc, - 0x80, 0xbe, 0xf5, 0x07, 0x14, 0x7d, 0x69, 0x81, 0xfe, 0x81, 0x22, 0xed, 0x63, 0xdf, 0xfb, 0x54, - 0xb4, 0x98, 0xdb, 0xee, 0xec, 0x72, 0x97, 0x52, 0xca, 0x26, 0x2f, 0xd6, 0xce, 0x37, 0xdf, 0x7c, - 0xb7, 0x99, 0xef, 0x32, 0xdf, 0xd0, 0x50, 0x70, 0xfa, 0xad, 0xe5, 0xbe, 0x63, 0x7b, 0x36, 0x2a, - 0x11, 0xaf, 0xd5, 0x76, 0x89, 0x33, 0x24, 0x4e, 0xff, 0xb0, 0x3e, 0xd7, 0xb1, 0x3b, 0x36, 0x9b, - 0x58, 0xa1, 0x5f, 0x1c, 0xa7, 0x3e, 0x4f, 0x71, 0x56, 0x7a, 0xc3, 0x56, 0x8b, 0xfd, 0xd3, 0x3f, - 0x5c, 0x39, 0x1e, 0x8a, 0xa9, 0x2b, 0x6c, 0xca, 0x18, 0x78, 0x47, 0xec, 0x9f, 0xfe, 0x21, 0xfb, - 0x23, 0x26, 0xaf, 0x76, 0x6c, 0xbb, 0xd3, 0x25, 0x2b, 0x46, 0xdf, 0x5c, 0x31, 0x2c, 0xcb, 0xf6, - 0x0c, 0xcf, 0xb4, 0x2d, 0x97, 0xcf, 0xe2, 0xcf, 0x34, 0xa8, 0xe8, 0xc4, 0xed, 0xdb, 0x96, 0x4b, - 0x36, 0x89, 0xd1, 0x26, 0x0e, 0xba, 0x06, 0xd0, 0xea, 0x0e, 0x5c, 0x8f, 0x38, 0x4d, 0xb3, 0x5d, - 0xd3, 0x16, 0xb5, 0xa5, 0x8c, 0x5e, 0x10, 0x90, 0xad, 0x36, 0xba, 0x02, 0x85, 0x1e, 0xe9, 0x1d, - 0xf2, 0xd9, 0x14, 0x9b, 0x9d, 0xe6, 0x80, 0xad, 0x36, 0xaa, 0xc3, 0xb4, 0x43, 0x86, 0xa6, 0x6b, - 0xda, 0x56, 0x2d, 0xbd, 0xa8, 0x2d, 0xa5, 0x75, 0x7f, 0x4c, 0x17, 0x3a, 0xc6, 0x0b, 0xaf, 0xe9, - 0x11, 0xa7, 0x57, 0xcb, 0xf0, 0x85, 0x14, 0x70, 0x40, 0x9c, 0x1e, 0xfe, 0x34, 0x0b, 0x25, 0xdd, - 0xb0, 0x3a, 0x44, 0x27, 0x1f, 0x0e, 0x88, 0xeb, 0xa1, 0x2a, 0xa4, 0x8f, 0xc9, 0x29, 0x63, 0x5f, - 0xd2, 0xe9, 0x27, 0x5f, 0x6f, 0x75, 0x48, 0x93, 0x58, 0x9c, 0x71, 0x89, 0xae, 0xb7, 0x3a, 0xa4, - 0x61, 0xb5, 0xd1, 0x1c, 0x64, 0xbb, 0x66, 0xcf, 0xf4, 0x04, 0x57, 0x3e, 0x08, 0x89, 0x93, 0x89, - 0x88, 0xb3, 0x0e, 0xe0, 0xda, 0x8e, 0xd7, 0xb4, 0x9d, 0x36, 0x71, 0x6a, 0xd9, 0x45, 0x6d, 0xa9, - 0xb2, 0x7a, 0x6b, 0x59, 0xdd, 0x88, 0x65, 0x55, 0xa0, 0xe5, 0x7d, 0xdb, 0xf1, 0xf6, 0x28, 0xae, - 0x5e, 0x70, 0xe5, 0x27, 0x7a, 0x07, 0x8a, 0x8c, 0x88, 0x67, 0x38, 0x1d, 0xe2, 0xd5, 0x72, 0x8c, - 0xca, 0xed, 0x33, 0xa8, 0x1c, 0x30, 0x64, 0x9d, 0xb1, 0xe7, 0xdf, 0x08, 0x43, 0xc9, 0x25, 0x8e, - 0x69, 0x74, 0xcd, 0x8f, 0x8c, 0xc3, 0x2e, 0xa9, 0xe5, 0x17, 0xb5, 0xa5, 0x69, 0x3d, 0x04, 0xa3, - 0xfa, 0x1f, 0x93, 0x53, 0xb7, 0x69, 0x5b, 0xdd, 0xd3, 0xda, 0x34, 0x43, 0x98, 0xa6, 0x80, 0x3d, - 0xab, 0x7b, 0xca, 0x36, 0xcd, 0x1e, 0x58, 0x1e, 0x9f, 0x2d, 0xb0, 0xd9, 0x02, 0x83, 0xb0, 0xe9, - 0x25, 0xa8, 0xf6, 0x4c, 0xab, 0xd9, 0xb3, 0xdb, 0x4d, 0xdf, 0x20, 0xc0, 0x0c, 0x52, 0xe9, 0x99, - 0xd6, 0x13, 0xbb, 0xad, 0x4b, 0xb3, 0x50, 0x4c, 0xe3, 0x24, 0x8c, 0x59, 0x14, 0x98, 0xc6, 0x89, - 0x8a, 0xb9, 0x0c, 0xb3, 0x94, 0x66, 0xcb, 0x21, 0x86, 0x47, 0x02, 0xe4, 0x12, 0x43, 0xbe, 0xd0, - 0x33, 0xad, 0x75, 0x36, 0x13, 0xc2, 0x37, 0x4e, 0x46, 0xf0, 0xcb, 0x02, 0xdf, 0x38, 0x09, 0xe3, - 0xe3, 0x65, 0x28, 0xf8, 0x36, 0x47, 0xd3, 0x90, 0xd9, 0xdd, 0xdb, 0x6d, 0x54, 0xa7, 0x10, 0x40, - 0x6e, 0x6d, 0x7f, 0xbd, 0xb1, 0xbb, 0x51, 0xd5, 0x50, 0x11, 0xf2, 0x1b, 0x0d, 0x3e, 0x48, 0xe1, - 0x47, 0x00, 0x81, 0x75, 0x51, 0x1e, 0xd2, 0xdb, 0x8d, 0xff, 0xaf, 0x4e, 0x51, 0x9c, 0xe7, 0x0d, - 0x7d, 0x7f, 0x6b, 0x6f, 0xb7, 0xaa, 0xd1, 0xc5, 0xeb, 0x7a, 0x63, 0xed, 0xa0, 0x51, 0x4d, 0x51, - 0x8c, 0x27, 0x7b, 0x1b, 0xd5, 0x34, 0x2a, 0x40, 0xf6, 0xf9, 0xda, 0xce, 0xb3, 0x46, 0x35, 0x83, - 0x3f, 0xd7, 0xa0, 0x2c, 0xf6, 0x8b, 0xfb, 0x04, 0x7a, 0x13, 0x72, 0x47, 0xcc, 0x2f, 0xd8, 0x51, - 0x2c, 0xae, 0x5e, 0x8d, 0x6c, 0x6e, 0xc8, 0x77, 0x74, 0x81, 0x8b, 0x30, 0xa4, 0x8f, 0x87, 0x6e, - 0x2d, 0xb5, 0x98, 0x5e, 0x2a, 0xae, 0x56, 0x97, 0xb9, 0xc3, 0x2e, 0x6f, 0x93, 0xd3, 0xe7, 0x46, - 0x77, 0x40, 0x74, 0x3a, 0x89, 0x10, 0x64, 0x7a, 0xb6, 0x43, 0xd8, 0x89, 0x9d, 0xd6, 0xd9, 0x37, - 0x3d, 0xc6, 0x6c, 0xd3, 0xc4, 0x69, 0xe5, 0x03, 0xfc, 0x85, 0x06, 0xf0, 0x74, 0xe0, 0x25, 0xbb, - 0xc6, 0x1c, 0x64, 0x87, 0x94, 0xb0, 0x70, 0x0b, 0x3e, 0x60, 0x3e, 0x41, 0x0c, 0x97, 0xf8, 0x3e, - 0x41, 0x07, 0xe8, 0x32, 0xe4, 0xfb, 0x0e, 0x19, 0x36, 0x8f, 0x87, 0x8c, 0xc9, 0xb4, 0x9e, 0xa3, - 0xc3, 0xed, 0x21, 0xba, 0x01, 0x25, 0xb3, 0x63, 0xd9, 0x0e, 0x69, 0x72, 0x5a, 0x59, 0x36, 0x5b, - 0xe4, 0x30, 0x26, 0xb7, 0x82, 0xc2, 0x09, 0xe7, 0x54, 0x94, 0x1d, 0x0a, 0xc2, 0x16, 0x14, 0x99, - 0xa8, 0x13, 0x99, 0xef, 0x5e, 0x20, 0x63, 0x8a, 0x2d, 0x1b, 0x35, 0xa1, 0x90, 0x1a, 0x7f, 0x00, - 0x68, 0x83, 0x74, 0x89, 0x47, 0x26, 0x89, 0x1e, 0x8a, 0x4d, 0xd2, 0xaa, 0x4d, 0xf0, 0x8f, 0x35, - 0x98, 0x0d, 0x91, 0x9f, 0x48, 0xad, 0x1a, 0xe4, 0xdb, 0x8c, 0x18, 0x97, 0x20, 0xad, 0xcb, 0x21, - 0x7a, 0x00, 0xd3, 0x42, 0x00, 0xb7, 0x96, 0x4e, 0x38, 0x34, 0x79, 0x2e, 0x93, 0x8b, 0xff, 0xa6, - 0x41, 0x41, 0x28, 0xba, 0xd7, 0x47, 0x6b, 0x50, 0x76, 0xf8, 0xa0, 0xc9, 0xf4, 0x11, 0x12, 0xd5, - 0x93, 0x83, 0xd0, 0xe6, 0x94, 0x5e, 0x12, 0x4b, 0x18, 0x18, 0xfd, 0x0f, 0x14, 0x25, 0x89, 0xfe, - 0xc0, 0x13, 0x26, 0xaf, 0x85, 0x09, 0x04, 0xe7, 0x6f, 0x73, 0x4a, 0x07, 0x81, 0xfe, 0x74, 0xe0, - 0xa1, 0x03, 0x98, 0x93, 0x8b, 0xb9, 0x36, 0x42, 0x8c, 0x34, 0xa3, 0xb2, 0x18, 0xa6, 0x32, 0xba, - 0x55, 0x9b, 0x53, 0x3a, 0x12, 0xeb, 0x95, 0xc9, 0x47, 0x05, 0xc8, 0x0b, 0x28, 0xfe, 0xbb, 0x06, - 0x20, 0x0d, 0xba, 0xd7, 0x47, 0x1b, 0x50, 0x71, 0xc4, 0x28, 0xa4, 0xf0, 0x95, 0x58, 0x85, 0xc5, - 0x3e, 0x4c, 0xe9, 0x65, 0xb9, 0x88, 0xab, 0xfc, 0x36, 0x94, 0x7c, 0x2a, 0x81, 0xce, 0xf3, 0x31, - 0x3a, 0xfb, 0x14, 0x8a, 0x72, 0x01, 0xd5, 0xfa, 0x3d, 0xb8, 0xe8, 0xaf, 0x8f, 0x51, 0xfb, 0xc6, - 0x18, 0xb5, 0x7d, 0x82, 0xb3, 0x92, 0x82, 0xaa, 0x38, 0xd0, 0x94, 0xc5, 0xc1, 0xf8, 0x8b, 0x34, - 0xe4, 0xd7, 0xed, 0x5e, 0xdf, 0x70, 0xe8, 0x1e, 0xe5, 0x1c, 0xe2, 0x0e, 0xba, 0x1e, 0x53, 0xb7, - 0xb2, 0x7a, 0x33, 0xcc, 0x41, 0xa0, 0xc9, 0xbf, 0x3a, 0x43, 0xd5, 0xc5, 0x12, 0xba, 0x58, 0x64, - 0xa8, 0xd4, 0x39, 0x16, 0x8b, 0xfc, 0x24, 0x96, 0x48, 0x5f, 0x4a, 0x07, 0xbe, 0x54, 0x87, 0xfc, - 0x90, 0x38, 0x41, 0x56, 0xdd, 0x9c, 0xd2, 0x25, 0x00, 0xdd, 0x83, 0x99, 0x68, 0x84, 0xcf, 0x0a, - 0x9c, 0x4a, 0x2b, 0x9c, 0x10, 0x6e, 0x42, 0x29, 0x94, 0x66, 0x72, 0x02, 0xaf, 0xd8, 0x53, 0xb2, - 0xcc, 0x25, 0x19, 0xda, 0x68, 0x4a, 0x2c, 0x6d, 0x4e, 0x89, 0xe0, 0x86, 0xff, 0x17, 0xca, 0x21, - 0x5d, 0x69, 0x14, 0x6f, 0xbc, 0xfb, 0x6c, 0x6d, 0x87, 0x87, 0xfc, 0xc7, 0x2c, 0xca, 0xeb, 0x55, - 0x8d, 0x66, 0x8e, 0x9d, 0xc6, 0xfe, 0x7e, 0x35, 0x85, 0xca, 0x50, 0xd8, 0xdd, 0x3b, 0x68, 0x72, - 0xac, 0x34, 0x7e, 0xcb, 0xa7, 0x20, 0x52, 0x86, 0x92, 0x29, 0xa6, 0x94, 0x4c, 0xa1, 0xc9, 0x4c, - 0x91, 0x0a, 0x32, 0x45, 0xfa, 0x51, 0x05, 0x4a, 0xdc, 0x3e, 0xcd, 0x81, 0x45, 0xb3, 0xd5, 0x2f, - 0x35, 0x80, 0x83, 0x13, 0x4b, 0x06, 0xa0, 0x15, 0xc8, 0xb7, 0x38, 0xf1, 0x9a, 0xc6, 0xfc, 0xf9, - 0x62, 0xac, 0xc9, 0x75, 0x89, 0x85, 0x5e, 0x87, 0xbc, 0x3b, 0x68, 0xb5, 0x88, 0x2b, 0xb3, 0xc6, - 0xe5, 0x68, 0x48, 0x11, 0x0e, 0xaf, 0x4b, 0x3c, 0xba, 0xe4, 0x85, 0x61, 0x76, 0x07, 0x2c, 0x87, - 0x8c, 0x5f, 0x22, 0xf0, 0xf0, 0xcf, 0x34, 0x28, 0x32, 0x29, 0x27, 0x8a, 0x63, 0x57, 0xa1, 0xc0, - 0x64, 0x20, 0x6d, 0x11, 0xc9, 0xa6, 0xf5, 0x00, 0x80, 0xfe, 0x1b, 0x0a, 0xf2, 0x04, 0xcb, 0x60, - 0x56, 0x8b, 0x27, 0xbb, 0xd7, 0xd7, 0x03, 0x54, 0xbc, 0x0d, 0x17, 0x98, 0x55, 0x5a, 0xb4, 0x3e, - 0x95, 0x76, 0x54, 0x2b, 0x38, 0x2d, 0x52, 0xc1, 0xd5, 0x61, 0xba, 0x7f, 0x74, 0xea, 0x9a, 0x2d, - 0xa3, 0x2b, 0xa4, 0xf0, 0xc7, 0xf8, 0xff, 0x00, 0xa9, 0xc4, 0x26, 0x51, 0x17, 0x97, 0xa1, 0xb8, - 0x69, 0xb8, 0x47, 0x42, 0x24, 0xfc, 0x3e, 0x94, 0xf8, 0x70, 0x22, 0x1b, 0x22, 0xc8, 0x1c, 0x19, - 0xee, 0x11, 0x13, 0xbc, 0xac, 0xb3, 0x6f, 0x7c, 0x01, 0x66, 0xf6, 0x2d, 0xa3, 0xef, 0x1e, 0xd9, - 0x32, 0xd6, 0xd2, 0xfa, 0xbc, 0x1a, 0xc0, 0x26, 0xe2, 0x78, 0x17, 0x66, 0x1c, 0xd2, 0x33, 0x4c, - 0xcb, 0xb4, 0x3a, 0xcd, 0xc3, 0x53, 0x8f, 0xb8, 0xa2, 0x7c, 0xaf, 0xf8, 0xe0, 0x47, 0x14, 0x4a, - 0x45, 0x3b, 0xec, 0xda, 0x87, 0xc2, 0xe3, 0xd9, 0x37, 0xfe, 0x8d, 0x06, 0xa5, 0xf7, 0x0c, 0xaf, - 0x25, 0xad, 0x80, 0xb6, 0xa0, 0xe2, 0xfb, 0x39, 0x83, 0x08, 0x59, 0x22, 0x01, 0x9f, 0xad, 0x91, - 0x85, 0x9d, 0x0c, 0xf8, 0xe5, 0x96, 0x0a, 0x60, 0xa4, 0x0c, 0xab, 0x45, 0xba, 0x3e, 0xa9, 0x54, - 0x32, 0x29, 0x86, 0xa8, 0x92, 0x52, 0x01, 0x8f, 0x66, 0x82, 0x64, 0xc8, 0xdd, 0xf2, 0xe7, 0x29, - 0x40, 0xa3, 0x32, 0x7c, 0xd5, 0xfa, 0xe0, 0x36, 0x54, 0x5c, 0xcf, 0x70, 0xbc, 0x66, 0xe4, 0x72, - 0x53, 0x66, 0x50, 0x3f, 0x56, 0xdd, 0x85, 0x99, 0xbe, 0x63, 0x77, 0x1c, 0xe2, 0xba, 0x4d, 0xcb, - 0xf6, 0xcc, 0x17, 0xa7, 0xa2, 0xc4, 0xaa, 0x48, 0xf0, 0x2e, 0x83, 0xa2, 0x06, 0xe4, 0x5f, 0x98, - 0x5d, 0x8f, 0x38, 0x6e, 0x2d, 0xbb, 0x98, 0x5e, 0xaa, 0xac, 0x3e, 0x38, 0xcb, 0x6a, 0xcb, 0xef, - 0x30, 0xfc, 0x83, 0xd3, 0x3e, 0xd1, 0xe5, 0x5a, 0xb5, 0x6c, 0xc9, 0x85, 0xca, 0x96, 0xdb, 0x00, - 0x01, 0x3e, 0x8d, 0x5a, 0xbb, 0x7b, 0x4f, 0x9f, 0x1d, 0x54, 0xa7, 0x50, 0x09, 0xa6, 0x77, 0xf7, - 0x36, 0x1a, 0x3b, 0x0d, 0x1a, 0xd7, 0xf0, 0x8a, 0xb4, 0x8d, 0x6a, 0x43, 0x34, 0x0f, 0xd3, 0x2f, - 0x29, 0x54, 0xde, 0xfe, 0xd2, 0x7a, 0x9e, 0x8d, 0xb7, 0xda, 0xf8, 0x47, 0x29, 0x28, 0x8b, 0x53, - 0x30, 0xd1, 0x51, 0x54, 0x59, 0xa4, 0x42, 0x2c, 0x68, 0x8d, 0xc4, 0x4f, 0x47, 0x5b, 0x94, 0x62, - 0x72, 0x48, 0xdd, 0x9d, 0x6f, 0x36, 0x69, 0x0b, 0xb3, 0xfa, 0x63, 0x74, 0x0f, 0xaa, 0x2d, 0xee, - 0xee, 0x91, 0xb4, 0xa3, 0xcf, 0x08, 0xb8, 0x92, 0x75, 0xca, 0xfe, 0x69, 0x33, 0x5c, 0x91, 0x76, - 0x0a, 0x7a, 0x49, 0x1e, 0x24, 0x0a, 0x43, 0xb7, 0x21, 0x47, 0x86, 0xc4, 0xf2, 0xdc, 0x5a, 0x91, - 0x05, 0xb0, 0xb2, 0xac, 0xc6, 0x1a, 0x14, 0xaa, 0x8b, 0x49, 0xfc, 0x5f, 0x70, 0x81, 0x55, 0xbd, - 0x8f, 0x1d, 0xc3, 0x52, 0xcb, 0xf3, 0x83, 0x83, 0x1d, 0x61, 0x3a, 0xfa, 0x89, 0x2a, 0x90, 0xda, - 0xda, 0x10, 0x8a, 0xa6, 0xb6, 0x36, 0xf0, 0x27, 0x1a, 0x20, 0x75, 0xdd, 0x44, 0xb6, 0x8c, 0x10, - 0x97, 0xec, 0xd3, 0x01, 0xfb, 0x39, 0xc8, 0x12, 0xc7, 0xb1, 0x1d, 0x66, 0xb5, 0x82, 0xce, 0x07, - 0xf8, 0x96, 0x90, 0x41, 0x27, 0x43, 0xfb, 0xd8, 0x77, 0x0c, 0x4e, 0x4d, 0xf3, 0x45, 0xdd, 0x86, - 0xd9, 0x10, 0xd6, 0x44, 0x81, 0xf4, 0x2e, 0x5c, 0x64, 0xc4, 0xb6, 0x09, 0xe9, 0xaf, 0x75, 0xcd, - 0x61, 0x22, 0xd7, 0x3e, 0x5c, 0x8a, 0x22, 0x7e, 0xbd, 0x36, 0xc2, 0x6f, 0x09, 0x8e, 0x07, 0x66, - 0x8f, 0x1c, 0xd8, 0x3b, 0xc9, 0xb2, 0xd1, 0xe8, 0x48, 0x6f, 0xdd, 0x22, 0xe3, 0xb0, 0x6f, 0xfc, - 0x2b, 0x0d, 0x2e, 0x8f, 0x2c, 0xff, 0x9a, 0x77, 0x75, 0x01, 0xa0, 0x43, 0x8f, 0x0f, 0x69, 0xd3, - 0x09, 0x7e, 0x5f, 0x54, 0x20, 0xbe, 0x9c, 0x34, 0xc0, 0x94, 0x84, 0x9c, 0x47, 0x90, 0x7b, 0xc2, - 0x5a, 0x35, 0x8a, 0x56, 0x19, 0xa9, 0x95, 0x65, 0xf4, 0xf8, 0x05, 0xb2, 0xa0, 0xb3, 0x6f, 0x96, - 0x5f, 0x09, 0x71, 0x9e, 0xe9, 0x3b, 0x3c, 0x8f, 0x17, 0x74, 0x7f, 0x4c, 0xb9, 0xb7, 0xba, 0x26, - 0xb1, 0x3c, 0x36, 0x9b, 0x61, 0xb3, 0x0a, 0x04, 0x2f, 0x43, 0x95, 0x73, 0x5a, 0x6b, 0xb7, 0x95, - 0x5c, 0xee, 0xd3, 0xd3, 0xc2, 0xf4, 0xf0, 0xaf, 0x35, 0xb8, 0xa0, 0x2c, 0x98, 0xc8, 0x76, 0xaf, - 0x40, 0x8e, 0x37, 0xa4, 0x44, 0x1e, 0x99, 0x0b, 0xaf, 0xe2, 0x6c, 0x74, 0x81, 0x83, 0x96, 0x21, - 0xcf, 0xbf, 0x64, 0xb1, 0x12, 0x8f, 0x2e, 0x91, 0xf0, 0x6d, 0x98, 0x15, 0x20, 0xd2, 0xb3, 0xe3, - 0x8e, 0x09, 0x33, 0x28, 0xfe, 0x18, 0xe6, 0xc2, 0x68, 0x13, 0xa9, 0xa4, 0x08, 0x99, 0x3a, 0x8f, - 0x90, 0x6b, 0x52, 0xc8, 0x67, 0xfd, 0xb6, 0x92, 0xf6, 0xa2, 0xbb, 0xae, 0xee, 0x48, 0x2a, 0xb2, - 0x23, 0xbe, 0x02, 0x92, 0xc4, 0x37, 0xaa, 0xc0, 0xac, 0x3c, 0x0e, 0x3b, 0xa6, 0xeb, 0x17, 0x43, - 0x1f, 0x01, 0x52, 0x81, 0xdf, 0xb4, 0x40, 0x1b, 0xe4, 0x85, 0x63, 0x74, 0x7a, 0xc4, 0x0f, 0xf5, - 0xb4, 0xca, 0x54, 0x81, 0x13, 0x05, 0xc7, 0x3f, 0x68, 0x50, 0x5a, 0xeb, 0x1a, 0x4e, 0x4f, 0x6e, - 0xd6, 0xdb, 0x90, 0xe3, 0xe5, 0xab, 0xb8, 0xf1, 0xdd, 0x09, 0x93, 0x51, 0x71, 0xf9, 0x60, 0x8d, - 0x17, 0xbb, 0x62, 0x15, 0xdd, 0x5c, 0xd1, 0x97, 0xdd, 0x88, 0xf4, 0x69, 0x37, 0xd0, 0xab, 0x90, - 0x35, 0xe8, 0x12, 0x16, 0x50, 0x2a, 0xd1, 0x8b, 0x03, 0xa3, 0xc6, 0x4a, 0x0d, 0x8e, 0x85, 0xdf, - 0x84, 0xa2, 0xc2, 0x81, 0xde, 0x87, 0x1e, 0x37, 0x44, 0x39, 0xb1, 0xb6, 0x7e, 0xb0, 0xf5, 0x9c, - 0x5f, 0x93, 0x2a, 0x00, 0x1b, 0x0d, 0x7f, 0x9c, 0xc2, 0xef, 0x8b, 0x55, 0x22, 0xe4, 0xa8, 0xf2, - 0x68, 0x49, 0xf2, 0xa4, 0xce, 0x25, 0xcf, 0x09, 0x94, 0x85, 0xfa, 0x13, 0x9d, 0x81, 0xd7, 0x21, - 0xc7, 0xe8, 0xc9, 0x23, 0x30, 0x1f, 0xc3, 0x56, 0x46, 0x0b, 0x8e, 0x88, 0x67, 0xa0, 0xbc, 0xef, - 0x19, 0xde, 0xc0, 0x95, 0x47, 0xe0, 0xf7, 0x1a, 0x54, 0x24, 0x64, 0xd2, 0xe6, 0x90, 0xbc, 0x54, - 0xf3, 0x20, 0xec, 0x5f, 0xa9, 0x2f, 0x41, 0xae, 0x7d, 0xb8, 0x6f, 0x7e, 0x24, 0x1b, 0x79, 0x62, - 0x44, 0xe1, 0x5d, 0xce, 0x87, 0x77, 0xd3, 0xc5, 0x88, 0x5e, 0xcf, 0x1c, 0xe3, 0x85, 0xb7, 0x65, - 0xb5, 0xc9, 0x09, 0xab, 0x82, 0x32, 0x7a, 0x00, 0x60, 0x37, 0x2a, 0xd1, 0x75, 0x67, 0xa5, 0x8f, - 0xda, 0x85, 0x9f, 0x85, 0x0b, 0x6b, 0x03, 0xef, 0xa8, 0x61, 0x19, 0x87, 0x5d, 0x19, 0x34, 0xf0, - 0x1c, 0x20, 0x0a, 0xdc, 0x30, 0x5d, 0x15, 0xda, 0x80, 0x59, 0x0a, 0x25, 0x96, 0x67, 0xb6, 0x94, - 0x08, 0x23, 0xf3, 0x88, 0x16, 0xc9, 0x23, 0x86, 0xeb, 0xbe, 0xb4, 0x9d, 0xb6, 0x50, 0xcd, 0x1f, - 0xe3, 0x0d, 0x4e, 0xfc, 0x99, 0x1b, 0xca, 0x14, 0x5f, 0x95, 0xca, 0x52, 0x40, 0xe5, 0x31, 0xf1, - 0xc6, 0x50, 0xc1, 0x0f, 0xe0, 0xa2, 0xc4, 0x14, 0x5d, 0x97, 0x31, 0xc8, 0x7b, 0x70, 0x4d, 0x22, - 0xaf, 0x1f, 0xd1, 0xbb, 0xc0, 0x53, 0xc1, 0xf0, 0xdf, 0x95, 0xf3, 0x11, 0xd4, 0x7c, 0x39, 0x59, - 0xe9, 0x67, 0x77, 0x55, 0x01, 0x06, 0xae, 0x38, 0x33, 0x05, 0x9d, 0x7d, 0x53, 0x98, 0x63, 0x77, - 0xfd, 0xac, 0x4c, 0xbf, 0xf1, 0x3a, 0xcc, 0x4b, 0x1a, 0xa2, 0x28, 0x0b, 0x13, 0x19, 0x11, 0x28, - 0x8e, 0x88, 0x30, 0x18, 0x5d, 0x3a, 0xde, 0xec, 0x2a, 0x66, 0xd8, 0xb4, 0x8c, 0xa6, 0xa6, 0xd0, - 0xbc, 0xc8, 0x4f, 0x04, 0x15, 0x4c, 0x0d, 0xda, 0x02, 0x4c, 0x09, 0xa8, 0x60, 0xb1, 0x11, 0x14, - 0x3c, 0xb2, 0x11, 0x23, 0xa4, 0x3f, 0x80, 0x05, 0x5f, 0x08, 0x6a, 0xb7, 0xa7, 0xc4, 0xe9, 0x99, - 0xae, 0xab, 0xf4, 0x09, 0xe2, 0x14, 0xbf, 0x03, 0x99, 0x3e, 0x11, 0x31, 0xa5, 0xb8, 0x8a, 0x96, - 0xf9, 0xdb, 0xd8, 0xb2, 0xb2, 0x98, 0xcd, 0xe3, 0x36, 0x5c, 0x97, 0xd4, 0xb9, 0x45, 0x63, 0xc9, - 0x47, 0x85, 0x92, 0x77, 0x48, 0x6e, 0xd6, 0xd1, 0x3b, 0x64, 0x9a, 0xef, 0xbd, 0xbc, 0x43, 0xd2, - 0x5c, 0xa1, 0xfa, 0xd6, 0x44, 0xb9, 0x62, 0x9b, 0xdb, 0xd4, 0x77, 0xc9, 0x89, 0x88, 0x1d, 0xc2, - 0x5c, 0xd8, 0x93, 0x27, 0x0a, 0x63, 0x73, 0x90, 0xf5, 0xec, 0x63, 0x22, 0x83, 0x18, 0x1f, 0x48, - 0x81, 0x7d, 0x37, 0x9f, 0x48, 0x60, 0x23, 0x20, 0xc6, 0x8e, 0xe4, 0xa4, 0xf2, 0xd2, 0xdd, 0x94, - 0xf5, 0x0f, 0x1f, 0xe0, 0x5d, 0xb8, 0x14, 0x0d, 0x13, 0x13, 0x89, 0xfc, 0x9c, 0x1f, 0xe0, 0xb8, - 0x48, 0x32, 0x11, 0xdd, 0x77, 0x83, 0x60, 0xa0, 0x04, 0x94, 0x89, 0x48, 0xea, 0x50, 0x8f, 0x8b, - 0x2f, 0xff, 0x89, 0xf3, 0xea, 0x87, 0x9b, 0x89, 0x88, 0xb9, 0x01, 0xb1, 0xc9, 0xb7, 0x3f, 0x88, - 0x11, 0xe9, 0xb1, 0x31, 0x42, 0x38, 0x49, 0x10, 0xc5, 0xbe, 0x86, 0x43, 0x27, 0x78, 0x04, 0x01, - 0x74, 0x52, 0x1e, 0x34, 0x87, 0xf8, 0x3c, 0xd8, 0x40, 0x1e, 0x6c, 0x35, 0xec, 0x4e, 0xb4, 0x19, - 0xef, 0x05, 0xb1, 0x73, 0x24, 0x32, 0x4f, 0x44, 0xf8, 0x7d, 0x58, 0x4c, 0x0e, 0xca, 0x93, 0x50, - 0xbe, 0x8f, 0xa1, 0xe0, 0x17, 0x94, 0xca, 0xbb, 0x72, 0x11, 0xf2, 0xbb, 0x7b, 0xfb, 0x4f, 0xd7, - 0xd6, 0x1b, 0x55, 0x6d, 0xf5, 0x1f, 0x69, 0x48, 0x6d, 0x3f, 0x47, 0xdf, 0x82, 0x2c, 0x7f, 0x2e, - 0x1a, 0xf3, 0x9a, 0x56, 0x1f, 0xf7, 0xf0, 0x84, 0xaf, 0x7e, 0xf2, 0xa7, 0xbf, 0x7e, 0x9e, 0xba, - 0x84, 0x2f, 0xac, 0x0c, 0xdf, 0x30, 0xba, 0xfd, 0x23, 0x63, 0xe5, 0x78, 0xb8, 0xc2, 0x72, 0xc2, - 0x43, 0xed, 0x3e, 0x7a, 0x0e, 0xe9, 0xa7, 0x03, 0x0f, 0x25, 0x3e, 0xb5, 0xd5, 0x93, 0x1f, 0xa4, - 0x70, 0x9d, 0x51, 0x9e, 0xc3, 0x33, 0x2a, 0xe5, 0xfe, 0xc0, 0xa3, 0x74, 0x87, 0x50, 0x54, 0xde, - 0x94, 0xd0, 0x99, 0x8f, 0x70, 0xf5, 0xb3, 0xdf, 0xab, 0x30, 0x66, 0xfc, 0xae, 0xe2, 0xcb, 0x2a, - 0x3f, 0xfe, 0xf4, 0xa5, 0xea, 0x73, 0x70, 0x62, 0x45, 0xf5, 0x09, 0x9e, 0x45, 0xa2, 0xfa, 0x28, - 0x4f, 0x11, 0xf1, 0xfa, 0x78, 0x27, 0x16, 0xa5, 0x6b, 0x8b, 0x77, 0xb0, 0x96, 0x87, 0xae, 0xc7, - 0xbc, 0xa3, 0xa8, 0x2f, 0x06, 0xf5, 0xc5, 0x64, 0x04, 0xc1, 0xe9, 0x06, 0xe3, 0x74, 0x05, 0x5f, - 0x52, 0x39, 0xb5, 0x7c, 0xbc, 0x87, 0xda, 0xfd, 0xd5, 0x23, 0xc8, 0xb2, 0x3e, 0x27, 0x6a, 0xca, - 0x8f, 0x7a, 0x4c, 0x87, 0x36, 0xe1, 0x04, 0x84, 0x3a, 0xa4, 0x78, 0x9e, 0x71, 0x9b, 0xc5, 0x15, - 0x9f, 0x1b, 0x6b, 0x75, 0x3e, 0xd4, 0xee, 0x2f, 0x69, 0xaf, 0x69, 0xab, 0xdf, 0xcb, 0x40, 0x96, - 0xb5, 0x8e, 0x50, 0x1f, 0x20, 0x68, 0x0a, 0x46, 0xf5, 0x1c, 0x69, 0x33, 0x46, 0xf5, 0x1c, 0xed, - 0x27, 0xe2, 0xeb, 0x8c, 0xf3, 0x3c, 0x9e, 0xf3, 0x39, 0xb3, 0x57, 0xfb, 0x15, 0xd6, 0x24, 0xa2, - 0x66, 0x7d, 0x09, 0x45, 0xa5, 0xb9, 0x87, 0xe2, 0x28, 0x86, 0xba, 0x83, 0xd1, 0x63, 0x12, 0xd3, - 0x19, 0xc4, 0x37, 0x19, 0xd3, 0x6b, 0xb8, 0xa6, 0x1a, 0x97, 0xf3, 0x75, 0x18, 0x26, 0x65, 0xfc, - 0xa9, 0x06, 0x95, 0x70, 0x83, 0x0f, 0xdd, 0x8c, 0x21, 0x1d, 0xed, 0x13, 0xd6, 0x6f, 0x8d, 0x47, - 0x4a, 0x14, 0x81, 0xf3, 0x3f, 0x26, 0xa4, 0x6f, 0x50, 0x4c, 0x61, 0x7b, 0xf4, 0x7d, 0x0d, 0x66, - 0x22, 0x6d, 0x3b, 0x14, 0xc7, 0x62, 0xa4, 0x29, 0x58, 0xbf, 0x7d, 0x06, 0x96, 0x90, 0xe4, 0x2e, - 0x93, 0xe4, 0x06, 0xbe, 0x3a, 0x6a, 0x0c, 0xcf, 0xec, 0x11, 0xcf, 0x16, 0xd2, 0xac, 0xfe, 0x33, - 0x0d, 0xf9, 0x75, 0xfe, 0x13, 0x2b, 0xe4, 0x41, 0xc1, 0xef, 0x84, 0xa1, 0x85, 0xb8, 0xae, 0x44, - 0x50, 0xb2, 0xd7, 0xaf, 0x27, 0xce, 0x0b, 0x11, 0xee, 0x30, 0x11, 0x16, 0xf1, 0x15, 0x5f, 0x04, - 0xf1, 0x53, 0xae, 0x15, 0x7e, 0xf9, 0x5e, 0x31, 0xda, 0x6d, 0xba, 0x25, 0xdf, 0xd5, 0xa0, 0xa4, - 0x36, 0xac, 0xd0, 0x8d, 0xd8, 0x7e, 0x88, 0xda, 0xf3, 0xaa, 0xe3, 0x71, 0x28, 0x82, 0xff, 0x3d, - 0xc6, 0xff, 0x26, 0x5e, 0x48, 0xe2, 0xef, 0x30, 0xfc, 0xb0, 0x08, 0xbc, 0xe5, 0x14, 0x2f, 0x42, - 0xa8, 0xa3, 0x15, 0x2f, 0x42, 0xb8, 0x63, 0x75, 0xb6, 0x08, 0x03, 0x86, 0x4f, 0x45, 0x38, 0x01, - 0x08, 0x3a, 0x4c, 0x28, 0xd6, 0xb8, 0xca, 0x25, 0x26, 0xea, 0x83, 0xa3, 0xcd, 0xa9, 0x98, 0x13, - 0x10, 0xe1, 0xdd, 0x35, 0x5d, 0xea, 0x8b, 0xab, 0xbf, 0xcd, 0x40, 0xf1, 0x89, 0x61, 0x5a, 0x1e, - 0xb1, 0x0c, 0xab, 0x45, 0x50, 0x07, 0xb2, 0x2c, 0x4b, 0x45, 0x03, 0x8f, 0xda, 0xf6, 0x89, 0x06, - 0x9e, 0x50, 0x4f, 0x04, 0xdf, 0x66, 0xac, 0xaf, 0xe3, 0xba, 0xcf, 0xba, 0x17, 0xd0, 0x5f, 0x61, - 0xfd, 0x0c, 0xaa, 0xf2, 0x31, 0xe4, 0x78, 0xff, 0x02, 0x45, 0xa8, 0x85, 0xfa, 0x1c, 0xf5, 0xab, - 0xf1, 0x93, 0x89, 0xa7, 0x4c, 0xe5, 0xe5, 0x32, 0x64, 0xca, 0xec, 0xdb, 0x00, 0x41, 0xc3, 0x2c, - 0x6a, 0xdf, 0x91, 0xfe, 0x5a, 0x7d, 0x31, 0x19, 0x41, 0x30, 0xbe, 0xcf, 0x18, 0xdf, 0xc2, 0xd7, - 0x63, 0x19, 0xb7, 0xfd, 0x05, 0x94, 0x79, 0x0b, 0x32, 0x9b, 0x86, 0x7b, 0x84, 0x22, 0x49, 0x48, - 0x79, 0xdb, 0xad, 0xd7, 0xe3, 0xa6, 0x04, 0xab, 0x5b, 0x8c, 0xd5, 0x02, 0x9e, 0x8f, 0x65, 0x75, - 0x64, 0xb8, 0x34, 0xa6, 0xa3, 0x01, 0x4c, 0xcb, 0xf7, 0x5a, 0x74, 0x2d, 0x62, 0xb3, 0xf0, 0xdb, - 0x6e, 0x7d, 0x21, 0x69, 0x5a, 0x30, 0x5c, 0x62, 0x0c, 0x31, 0xbe, 0x16, 0x6f, 0x54, 0x81, 0xfe, - 0x50, 0xbb, 0xff, 0x9a, 0xb6, 0xfa, 0xc3, 0x2a, 0x64, 0x68, 0xbd, 0x44, 0xb3, 0x48, 0x70, 0xcd, - 0x8c, 0x5a, 0x78, 0xa4, 0xb9, 0x13, 0xb5, 0xf0, 0xe8, 0x0d, 0x35, 0x26, 0x8b, 0xb0, 0x1f, 0x9a, - 0x12, 0x86, 0x45, 0x35, 0xf6, 0xa0, 0xa8, 0x5c, 0x46, 0x51, 0x0c, 0xc5, 0x70, 0xeb, 0x28, 0x9a, - 0x45, 0x62, 0x6e, 0xb2, 0x78, 0x91, 0x31, 0xad, 0xe3, 0x8b, 0x61, 0xa6, 0x6d, 0x8e, 0x46, 0xb9, - 0x7e, 0x0c, 0x25, 0xf5, 0xd6, 0x8a, 0x62, 0x88, 0x46, 0x7a, 0x53, 0xd1, 0x58, 0x11, 0x77, 0xe9, - 0x8d, 0x71, 0x1a, 0xff, 0x67, 0xb5, 0x12, 0x97, 0x72, 0xff, 0x10, 0xf2, 0xe2, 0x2e, 0x1b, 0xa7, - 0x6f, 0xb8, 0x9b, 0x15, 0xa7, 0x6f, 0xe4, 0x22, 0x1c, 0x53, 0x92, 0x30, 0xb6, 0xb4, 0x66, 0x97, - 0x01, 0x5a, 0xb0, 0x7c, 0x4c, 0xbc, 0x24, 0x96, 0x41, 0x7f, 0x26, 0x89, 0xa5, 0x72, 0x5f, 0x1a, - 0xcb, 0xb2, 0x43, 0x3c, 0x71, 0x96, 0xe5, 0x65, 0x04, 0x25, 0x50, 0x54, 0xa3, 0x21, 0x1e, 0x87, - 0x92, 0x58, 0x45, 0x06, 0x5c, 0x45, 0x28, 0x44, 0xdf, 0x01, 0x08, 0x2e, 0xde, 0xd1, 0xc2, 0x20, - 0xb6, 0x7b, 0x17, 0x2d, 0x0c, 0xe2, 0xef, 0xee, 0x31, 0x1e, 0x1c, 0x30, 0xe7, 0x95, 0x2c, 0x65, - 0xff, 0x13, 0x0d, 0xd0, 0xe8, 0x45, 0x1d, 0x3d, 0x88, 0x67, 0x11, 0xdb, 0x18, 0xac, 0xbf, 0x72, - 0x3e, 0xe4, 0xc4, 0xe8, 0x19, 0xc8, 0xd5, 0x62, 0x4b, 0xfa, 0x2f, 0xa9, 0x64, 0x9f, 0x69, 0x50, - 0x0e, 0x5d, 0xf5, 0xd1, 0x9d, 0x84, 0x7d, 0x8e, 0x34, 0x17, 0xeb, 0x77, 0xcf, 0xc4, 0x4b, 0xac, - 0x9d, 0x94, 0x53, 0x21, 0xeb, 0xc6, 0x1f, 0x68, 0x50, 0x09, 0xf7, 0x07, 0x50, 0x02, 0x83, 0x91, - 0x0e, 0x65, 0x7d, 0xe9, 0x6c, 0xc4, 0x73, 0xec, 0x56, 0x50, 0x4a, 0x7e, 0x08, 0x79, 0xd1, 0x56, - 0x88, 0x73, 0x8b, 0x70, 0x83, 0x33, 0xce, 0x2d, 0x22, 0x3d, 0x89, 0x24, 0xb7, 0xa0, 0x37, 0x74, - 0xc5, 0x13, 0x45, 0xf3, 0x21, 0x89, 0xe5, 0x78, 0x4f, 0x8c, 0x74, 0x2e, 0xc6, 0xb2, 0x0c, 0x3c, - 0x51, 0xb6, 0x1e, 0x50, 0x02, 0xc5, 0x33, 0x3c, 0x31, 0xda, 0xb9, 0x48, 0xf2, 0x44, 0xc6, 0x55, - 0xf1, 0xc4, 0xa0, 0x53, 0x10, 0xe7, 0x89, 0x23, 0xed, 0xdb, 0x38, 0x4f, 0x1c, 0x6d, 0x36, 0x24, - 0xed, 0x2d, 0x63, 0x1e, 0xf2, 0xc4, 0xd9, 0x98, 0xce, 0x02, 0x7a, 0x25, 0xc1, 0xa6, 0xb1, 0xad, - 0xe1, 0xfa, 0xab, 0xe7, 0xc4, 0x1e, 0xef, 0x01, 0x7c, 0x37, 0xa4, 0x07, 0xfc, 0x42, 0x83, 0xb9, - 0xb8, 0xd6, 0x04, 0x4a, 0x60, 0x96, 0xd0, 0x57, 0xae, 0x2f, 0x9f, 0x17, 0xfd, 0x1c, 0x76, 0xf3, - 0x7d, 0xe2, 0x51, 0xf5, 0x77, 0x5f, 0x2e, 0x68, 0x7f, 0xfc, 0x72, 0x41, 0xfb, 0xf3, 0x97, 0x0b, - 0xda, 0x4f, 0xff, 0xb2, 0x30, 0x75, 0x98, 0x63, 0xff, 0xdb, 0xe3, 0x8d, 0x7f, 0x05, 0x00, 0x00, - 0xff, 0xff, 0x63, 0x1c, 0x78, 0x24, 0x74, 0x32, 0x00, 0x00, + 0xb9, 0x5a, 0x52, 0xbc, 0x7d, 0xbc, 0x88, 0x1e, 0xc9, 0x36, 0x45, 0xdb, 0xb2, 0x3c, 0xbe, 0xc9, + 0x76, 0x22, 0x25, 0x4a, 0xce, 0x79, 0xf0, 0x09, 0x82, 0x23, 0x4b, 0x8c, 0xa5, 0x48, 0x96, 0x9c, + 0x95, 0xec, 0xe4, 0x00, 0xc1, 0x21, 0x56, 0xe4, 0x98, 0x5a, 0x88, 0xdc, 0x65, 0x76, 0x97, 0xb4, + 0x94, 0x93, 0x03, 0x14, 0x69, 0x82, 0xa2, 0x05, 0xfa, 0xd2, 0x3c, 0xf4, 0xf6, 0x58, 0x14, 0x45, + 0x7f, 0x40, 0xdf, 0xfa, 0x5c, 0x14, 0x7d, 0x69, 0x81, 0xfe, 0x81, 0x22, 0xed, 0x63, 0xdf, 0xfb, + 0x54, 0xb4, 0x98, 0xdb, 0xee, 0xec, 0x72, 0x97, 0x52, 0xca, 0x26, 0x2f, 0xd6, 0xce, 0x37, 0xdf, + 0x7c, 0xb7, 0x99, 0xef, 0x32, 0xdf, 0xd0, 0x50, 0x70, 0xfa, 0xad, 0xe5, 0xbe, 0x63, 0x7b, 0x36, + 0x2a, 0x11, 0xaf, 0xd5, 0x76, 0x89, 0x33, 0x24, 0x4e, 0xff, 0xb0, 0x3e, 0xd7, 0xb1, 0x3b, 0x36, + 0x9b, 0x58, 0xa1, 0x5f, 0x1c, 0xa7, 0x3e, 0x4f, 0x71, 0x56, 0x7a, 0xc3, 0x56, 0x8b, 0xfd, 0xd3, + 0x3f, 0x5c, 0x39, 0x1e, 0x8a, 0xa9, 0x2b, 0x6c, 0xca, 0x18, 0x78, 0x47, 0xec, 0x9f, 0xfe, 0x21, + 0xfb, 0x23, 0x26, 0xaf, 0x76, 0x6c, 0xbb, 0xd3, 0x25, 0x2b, 0x46, 0xdf, 0x5c, 0x31, 0x2c, 0xcb, + 0xf6, 0x0c, 0xcf, 0xb4, 0x2d, 0x97, 0xcf, 0xe2, 0xcf, 0x35, 0xa8, 0xe8, 0xc4, 0xed, 0xdb, 0x96, + 0x4b, 0x36, 0x89, 0xd1, 0x26, 0x0e, 0xba, 0x06, 0xd0, 0xea, 0x0e, 0x5c, 0x8f, 0x38, 0x4d, 0xb3, + 0x5d, 0xd3, 0x16, 0xb5, 0xa5, 0x69, 0xbd, 0x20, 0x20, 0x5b, 0x6d, 0x74, 0x05, 0x0a, 0x3d, 0xd2, + 0x3b, 0xe4, 0xb3, 0x29, 0x36, 0x9b, 0xe7, 0x80, 0xad, 0x36, 0xaa, 0x43, 0xde, 0x21, 0x43, 0xd3, + 0x35, 0x6d, 0xab, 0x96, 0x5e, 0xd4, 0x96, 0xd2, 0xba, 0x3f, 0xa6, 0x0b, 0x1d, 0xe3, 0x85, 0xd7, + 0xf4, 0x88, 0xd3, 0xab, 0x4d, 0xf3, 0x85, 0x14, 0x70, 0x40, 0x9c, 0x1e, 0xfe, 0x2c, 0x03, 0x25, + 0xdd, 0xb0, 0x3a, 0x44, 0x27, 0x1f, 0x0d, 0x88, 0xeb, 0xa1, 0x2a, 0xa4, 0x8f, 0xc9, 0x29, 0x63, + 0x5f, 0xd2, 0xe9, 0x27, 0x5f, 0x6f, 0x75, 0x48, 0x93, 0x58, 0x9c, 0x71, 0x89, 0xae, 0xb7, 0x3a, + 0xa4, 0x61, 0xb5, 0xd1, 0x1c, 0x64, 0xba, 0x66, 0xcf, 0xf4, 0x04, 0x57, 0x3e, 0x08, 0x89, 0x33, + 0x1d, 0x11, 0x67, 0x1d, 0xc0, 0xb5, 0x1d, 0xaf, 0x69, 0x3b, 0x6d, 0xe2, 0xd4, 0x32, 0x8b, 0xda, + 0x52, 0x65, 0xf5, 0xd6, 0xb2, 0xba, 0x11, 0xcb, 0xaa, 0x40, 0xcb, 0xfb, 0xb6, 0xe3, 0xed, 0x51, + 0x5c, 0xbd, 0xe0, 0xca, 0x4f, 0xf4, 0x0e, 0x14, 0x19, 0x11, 0xcf, 0x70, 0x3a, 0xc4, 0xab, 0x65, + 0x19, 0x95, 0xdb, 0x67, 0x50, 0x39, 0x60, 0xc8, 0x3a, 0x63, 0xcf, 0xbf, 0x11, 0x86, 0x92, 0x4b, + 0x1c, 0xd3, 0xe8, 0x9a, 0x1f, 0x1b, 0x87, 0x5d, 0x52, 0xcb, 0x2d, 0x6a, 0x4b, 0x79, 0x3d, 0x04, + 0xa3, 0xfa, 0x1f, 0x93, 0x53, 0xb7, 0x69, 0x5b, 0xdd, 0xd3, 0x5a, 0x9e, 0x21, 0xe4, 0x29, 0x60, + 0xcf, 0xea, 0x9e, 0xb2, 0x4d, 0xb3, 0x07, 0x96, 0xc7, 0x67, 0x0b, 0x6c, 0xb6, 0xc0, 0x20, 0x6c, + 0x7a, 0x09, 0xaa, 0x3d, 0xd3, 0x6a, 0xf6, 0xec, 0x76, 0xd3, 0x37, 0x08, 0x30, 0x83, 0x54, 0x7a, + 0xa6, 0xf5, 0xc4, 0x6e, 0xeb, 0xd2, 0x2c, 0x14, 0xd3, 0x38, 0x09, 0x63, 0x16, 0x05, 0xa6, 0x71, + 0xa2, 0x62, 0x2e, 0xc3, 0x2c, 0xa5, 0xd9, 0x72, 0x88, 0xe1, 0x91, 0x00, 0xb9, 0xc4, 0x90, 0x2f, + 0xf4, 0x4c, 0x6b, 0x9d, 0xcd, 0x84, 0xf0, 0x8d, 0x93, 0x11, 0xfc, 0xb2, 0xc0, 0x37, 0x4e, 0xc2, + 0xf8, 0x78, 0x19, 0x0a, 0xbe, 0xcd, 0x51, 0x1e, 0xa6, 0x77, 0xf7, 0x76, 0x1b, 0xd5, 0x29, 0x04, + 0x90, 0x5d, 0xdb, 0x5f, 0x6f, 0xec, 0x6e, 0x54, 0x35, 0x54, 0x84, 0xdc, 0x46, 0x83, 0x0f, 0x52, + 0xf8, 0x11, 0x40, 0x60, 0x5d, 0x94, 0x83, 0xf4, 0x76, 0xe3, 0x7f, 0xaa, 0x53, 0x14, 0xe7, 0x79, + 0x43, 0xdf, 0xdf, 0xda, 0xdb, 0xad, 0x6a, 0x74, 0xf1, 0xba, 0xde, 0x58, 0x3b, 0x68, 0x54, 0x53, + 0x14, 0xe3, 0xc9, 0xde, 0x46, 0x35, 0x8d, 0x0a, 0x90, 0x79, 0xbe, 0xb6, 0xf3, 0xac, 0x51, 0x9d, + 0xc6, 0x5f, 0x68, 0x50, 0x16, 0xfb, 0xc5, 0x7d, 0x02, 0xbd, 0x09, 0xd9, 0x23, 0xe6, 0x17, 0xec, + 0x28, 0x16, 0x57, 0xaf, 0x46, 0x36, 0x37, 0xe4, 0x3b, 0xba, 0xc0, 0x45, 0x18, 0xd2, 0xc7, 0x43, + 0xb7, 0x96, 0x5a, 0x4c, 0x2f, 0x15, 0x57, 0xab, 0xcb, 0xdc, 0x61, 0x97, 0xb7, 0xc9, 0xe9, 0x73, + 0xa3, 0x3b, 0x20, 0x3a, 0x9d, 0x44, 0x08, 0xa6, 0x7b, 0xb6, 0x43, 0xd8, 0x89, 0xcd, 0xeb, 0xec, + 0x9b, 0x1e, 0x63, 0xb6, 0x69, 0xe2, 0xb4, 0xf2, 0x01, 0xfe, 0xa5, 0x06, 0xf0, 0x74, 0xe0, 0x25, + 0xbb, 0xc6, 0x1c, 0x64, 0x86, 0x94, 0xb0, 0x70, 0x0b, 0x3e, 0x60, 0x3e, 0x41, 0x0c, 0x97, 0xf8, + 0x3e, 0x41, 0x07, 0xe8, 0x32, 0xe4, 0xfa, 0x0e, 0x19, 0x36, 0x8f, 0x87, 0x8c, 0x49, 0x5e, 0xcf, + 0xd2, 0xe1, 0xf6, 0x10, 0xdd, 0x80, 0x92, 0xd9, 0xb1, 0x6c, 0x87, 0x34, 0x39, 0xad, 0x0c, 0x9b, + 0x2d, 0x72, 0x18, 0x93, 0x5b, 0x41, 0xe1, 0x84, 0xb3, 0x2a, 0xca, 0x0e, 0x05, 0x61, 0x0b, 0x8a, + 0x4c, 0xd4, 0x89, 0xcc, 0x77, 0x2f, 0x90, 0x31, 0xc5, 0x96, 0x8d, 0x9a, 0x50, 0x48, 0x8d, 0x3f, + 0x04, 0xb4, 0x41, 0xba, 0xc4, 0x23, 0x93, 0x44, 0x0f, 0xc5, 0x26, 0x69, 0xd5, 0x26, 0xf8, 0x07, + 0x1a, 0xcc, 0x86, 0xc8, 0x4f, 0xa4, 0x56, 0x0d, 0x72, 0x6d, 0x46, 0x8c, 0x4b, 0x90, 0xd6, 0xe5, + 0x10, 0x3d, 0x80, 0xbc, 0x10, 0xc0, 0xad, 0xa5, 0x13, 0x0e, 0x4d, 0x8e, 0xcb, 0xe4, 0xe2, 0xbf, + 0x6a, 0x50, 0x10, 0x8a, 0xee, 0xf5, 0xd1, 0x1a, 0x94, 0x1d, 0x3e, 0x68, 0x32, 0x7d, 0x84, 0x44, + 0xf5, 0xe4, 0x20, 0xb4, 0x39, 0xa5, 0x97, 0xc4, 0x12, 0x06, 0x46, 0xff, 0x05, 0x45, 0x49, 0xa2, + 0x3f, 0xf0, 0x84, 0xc9, 0x6b, 0x61, 0x02, 0xc1, 0xf9, 0xdb, 0x9c, 0xd2, 0x41, 0xa0, 0x3f, 0x1d, + 0x78, 0xe8, 0x00, 0xe6, 0xe4, 0x62, 0xae, 0x8d, 0x10, 0x23, 0xcd, 0xa8, 0x2c, 0x86, 0xa9, 0x8c, + 0x6e, 0xd5, 0xe6, 0x94, 0x8e, 0xc4, 0x7a, 0x65, 0xf2, 0x51, 0x01, 0x72, 0x02, 0x8a, 0xff, 0xa6, + 0x01, 0x48, 0x83, 0xee, 0xf5, 0xd1, 0x06, 0x54, 0x1c, 0x31, 0x0a, 0x29, 0x7c, 0x25, 0x56, 0x61, + 0xb1, 0x0f, 0x53, 0x7a, 0x59, 0x2e, 0xe2, 0x2a, 0xbf, 0x0d, 0x25, 0x9f, 0x4a, 0xa0, 0xf3, 0x7c, + 0x8c, 0xce, 0x3e, 0x85, 0xa2, 0x5c, 0x40, 0xb5, 0x7e, 0x1f, 0x2e, 0xfa, 0xeb, 0x63, 0xd4, 0xbe, + 0x31, 0x46, 0x6d, 0x9f, 0xe0, 0xac, 0xa4, 0xa0, 0x2a, 0x0e, 0x34, 0x65, 0x71, 0x30, 0xfe, 0x4d, + 0x1a, 0x72, 0xeb, 0x76, 0xaf, 0x6f, 0x38, 0x74, 0x8f, 0xb2, 0x0e, 0x71, 0x07, 0x5d, 0x8f, 0xa9, + 0x5b, 0x59, 0xbd, 0x19, 0xe6, 0x20, 0xd0, 0xe4, 0x5f, 0x9d, 0xa1, 0xea, 0x62, 0x09, 0x5d, 0x2c, + 0x32, 0x54, 0xea, 0x1c, 0x8b, 0x45, 0x7e, 0x12, 0x4b, 0xa4, 0x2f, 0xa5, 0x03, 0x5f, 0xaa, 0x43, + 0x6e, 0x48, 0x9c, 0x20, 0xab, 0x6e, 0x4e, 0xe9, 0x12, 0x80, 0xee, 0xc1, 0x4c, 0x34, 0xc2, 0x67, + 0x04, 0x4e, 0xa5, 0x15, 0x4e, 0x08, 0x37, 0xa1, 0x14, 0x4a, 0x33, 0x59, 0x81, 0x57, 0xec, 0x29, + 0x59, 0xe6, 0x92, 0x0c, 0x6d, 0x34, 0x25, 0x96, 0x36, 0xa7, 0x64, 0x70, 0x0b, 0xf9, 0x73, 0x3e, + 0xec, 0xcf, 0xf8, 0xbf, 0xa1, 0x1c, 0x32, 0x04, 0x0d, 0xf1, 0x8d, 0xf7, 0x9e, 0xad, 0xed, 0xf0, + 0x7c, 0xf0, 0x98, 0xa5, 0x00, 0xbd, 0xaa, 0xd1, 0xb4, 0xb2, 0xd3, 0xd8, 0xdf, 0xaf, 0xa6, 0x50, + 0x19, 0x0a, 0xbb, 0x7b, 0x07, 0x4d, 0x8e, 0x95, 0xc6, 0x6f, 0xf9, 0x14, 0x44, 0x3e, 0x51, 0xd2, + 0xc8, 0x94, 0x92, 0x46, 0x34, 0x99, 0x46, 0x52, 0x41, 0x1a, 0x49, 0x3f, 0xaa, 0x40, 0x89, 0x1b, + 0xaf, 0x39, 0xb0, 0x68, 0x2a, 0xfb, 0x99, 0x06, 0x70, 0x70, 0x62, 0xc9, 0xe8, 0xb4, 0x02, 0xb9, + 0x16, 0x27, 0x5e, 0xd3, 0x98, 0xb3, 0x5f, 0x8c, 0xdd, 0x0f, 0x5d, 0x62, 0xa1, 0xd7, 0x21, 0xe7, + 0x0e, 0x5a, 0x2d, 0xe2, 0xca, 0x94, 0x72, 0x39, 0x1a, 0x6f, 0x44, 0x34, 0xd0, 0x25, 0x1e, 0x5d, + 0xf2, 0xc2, 0x30, 0xbb, 0x03, 0x96, 0x60, 0xc6, 0x2f, 0x11, 0x78, 0xf8, 0xc7, 0x1a, 0x14, 0x99, + 0x94, 0x13, 0x05, 0xb9, 0xab, 0x50, 0x60, 0x32, 0x90, 0xb6, 0x08, 0x73, 0x79, 0x3d, 0x00, 0xa0, + 0xff, 0x84, 0x82, 0x3c, 0xde, 0x32, 0xd2, 0xd5, 0xe2, 0xc9, 0xee, 0xf5, 0xf5, 0x00, 0x15, 0x6f, + 0xc3, 0x05, 0x66, 0x95, 0x16, 0x2d, 0x5e, 0xa5, 0x1d, 0xd5, 0xf2, 0x4e, 0x8b, 0x94, 0x77, 0x75, + 0xc8, 0xf7, 0x8f, 0x4e, 0x5d, 0xb3, 0x65, 0x74, 0x85, 0x14, 0xfe, 0x18, 0xbf, 0x0b, 0x48, 0x25, + 0x36, 0x89, 0xba, 0xb8, 0x0c, 0xc5, 0x4d, 0xc3, 0x3d, 0x12, 0x22, 0xe1, 0x0f, 0xa0, 0xc4, 0x87, + 0x13, 0xd9, 0x10, 0xc1, 0xf4, 0x91, 0xe1, 0x1e, 0x31, 0xc1, 0xcb, 0x3a, 0xfb, 0xc6, 0x17, 0x60, + 0x66, 0xdf, 0x32, 0xfa, 0xee, 0x91, 0x2d, 0x03, 0x31, 0x2d, 0xde, 0xab, 0x01, 0x6c, 0x22, 0x8e, + 0x77, 0x61, 0xc6, 0x21, 0x3d, 0xc3, 0xb4, 0x4c, 0xab, 0xd3, 0x3c, 0x3c, 0xf5, 0x88, 0x2b, 0x6a, + 0xfb, 0x8a, 0x0f, 0x7e, 0x44, 0xa1, 0x54, 0xb4, 0xc3, 0xae, 0x7d, 0x28, 0xc2, 0x01, 0xfb, 0xc6, + 0xbf, 0xd2, 0xa0, 0xf4, 0xbe, 0xe1, 0xb5, 0xa4, 0x15, 0xd0, 0x16, 0x54, 0xfc, 0x20, 0xc0, 0x20, + 0x42, 0x96, 0x48, 0x36, 0x60, 0x6b, 0x64, 0xd5, 0x27, 0xb3, 0x41, 0xb9, 0xa5, 0x02, 0x18, 0x29, + 0xc3, 0x6a, 0x91, 0xae, 0x4f, 0x2a, 0x95, 0x4c, 0x8a, 0x21, 0xaa, 0xa4, 0x54, 0xc0, 0xa3, 0x99, + 0x20, 0x53, 0x72, 0xb7, 0xfc, 0x49, 0x0a, 0xd0, 0xa8, 0x0c, 0x5f, 0xb5, 0x78, 0xb8, 0x0d, 0x15, + 0xd7, 0x33, 0x1c, 0xaf, 0x19, 0xb9, 0xf9, 0x94, 0x19, 0xd4, 0x0f, 0x64, 0x77, 0x61, 0xa6, 0xef, + 0xd8, 0x1d, 0x87, 0xb8, 0x6e, 0xd3, 0xb2, 0x3d, 0xf3, 0xc5, 0xa9, 0xa8, 0xbf, 0x2a, 0x12, 0xbc, + 0xcb, 0xa0, 0xa8, 0x01, 0xb9, 0x17, 0x66, 0xd7, 0x23, 0x8e, 0x5b, 0xcb, 0x2c, 0xa6, 0x97, 0x2a, + 0xab, 0x0f, 0xce, 0xb2, 0xda, 0xf2, 0x3b, 0x0c, 0xff, 0xe0, 0xb4, 0x4f, 0x74, 0xb9, 0x56, 0xad, + 0x69, 0xb2, 0xa1, 0x9a, 0xe6, 0x36, 0x40, 0x80, 0x4f, 0xa3, 0xd6, 0xee, 0xde, 0xd3, 0x67, 0x07, + 0xd5, 0x29, 0x54, 0x82, 0xfc, 0xee, 0xde, 0x46, 0x63, 0xa7, 0x41, 0xe3, 0x1a, 0x5e, 0x91, 0xb6, + 0x51, 0x6d, 0x88, 0xe6, 0x21, 0xff, 0x92, 0x42, 0xe5, 0xd5, 0x30, 0xad, 0xe7, 0xd8, 0x78, 0xab, + 0x8d, 0xbf, 0x9f, 0x82, 0xb2, 0x38, 0x05, 0x13, 0x1d, 0x45, 0x95, 0x45, 0x2a, 0xc4, 0x82, 0x16, + 0x50, 0xfc, 0x74, 0xb4, 0x45, 0x9d, 0x26, 0x87, 0xd4, 0xdd, 0xf9, 0x66, 0x93, 0xb6, 0x30, 0xab, + 0x3f, 0x46, 0xf7, 0xa0, 0xda, 0xe2, 0xee, 0x1e, 0xc9, 0x49, 0xfa, 0x8c, 0x80, 0x2b, 0x29, 0xa9, + 0xec, 0x9f, 0x36, 0xc3, 0x15, 0x39, 0xa9, 0xa0, 0x97, 0xe4, 0x41, 0xa2, 0x30, 0x74, 0x1b, 0xb2, + 0x64, 0x48, 0x2c, 0xcf, 0xad, 0x15, 0x59, 0x00, 0x2b, 0xcb, 0x52, 0xad, 0x41, 0xa1, 0xba, 0x98, + 0xc4, 0xff, 0x01, 0x17, 0x58, 0x49, 0xfc, 0xd8, 0x31, 0x2c, 0xb5, 0x76, 0x3f, 0x38, 0xd8, 0x11, + 0xa6, 0xa3, 0x9f, 0xa8, 0x02, 0xa9, 0xad, 0x0d, 0xa1, 0x68, 0x6a, 0x6b, 0x03, 0x7f, 0xaa, 0x01, + 0x52, 0xd7, 0x4d, 0x64, 0xcb, 0x08, 0x71, 0xc9, 0x3e, 0x1d, 0xb0, 0x9f, 0x83, 0x0c, 0x71, 0x1c, + 0xdb, 0x61, 0x56, 0x2b, 0xe8, 0x7c, 0x80, 0x6f, 0x09, 0x19, 0x74, 0x32, 0xb4, 0x8f, 0x7d, 0xc7, + 0xe0, 0xd4, 0x34, 0x5f, 0xd4, 0x6d, 0x98, 0x0d, 0x61, 0x4d, 0x14, 0x48, 0xef, 0xc2, 0x45, 0x46, + 0x6c, 0x9b, 0x90, 0xfe, 0x5a, 0xd7, 0x1c, 0x26, 0x72, 0xed, 0xc3, 0xa5, 0x28, 0xe2, 0xd7, 0x6b, + 0x23, 0xfc, 0x96, 0xe0, 0x78, 0x60, 0xf6, 0xc8, 0x81, 0xbd, 0x93, 0x2c, 0x1b, 0x8d, 0x8e, 0xf4, + 0x4a, 0x2e, 0x32, 0x0e, 0xfb, 0xc6, 0x3f, 0xd7, 0xe0, 0xf2, 0xc8, 0xf2, 0xaf, 0x79, 0x57, 0x17, + 0x00, 0x3a, 0xf4, 0xf8, 0x90, 0x36, 0x9d, 0xe0, 0x97, 0x49, 0x05, 0xe2, 0xcb, 0x49, 0x03, 0x4c, + 0x49, 0xc8, 0x79, 0x04, 0xd9, 0x27, 0xac, 0x8f, 0xa3, 0x68, 0x35, 0x2d, 0xb5, 0xb2, 0x8c, 0x1e, + 0xbf, 0x5d, 0x16, 0x74, 0xf6, 0xcd, 0xf2, 0x2b, 0x21, 0xce, 0x33, 0x7d, 0x87, 0xe7, 0xf1, 0x82, + 0xee, 0x8f, 0x29, 0xf7, 0x56, 0xd7, 0x24, 0x96, 0xc7, 0x66, 0xa7, 0xd9, 0xac, 0x02, 0xc1, 0xcb, + 0x50, 0xe5, 0x9c, 0xd6, 0xda, 0x6d, 0x25, 0x97, 0xfb, 0xf4, 0xb4, 0x30, 0x3d, 0xfc, 0x0b, 0x0d, + 0x2e, 0x28, 0x0b, 0x26, 0xb2, 0xdd, 0x2b, 0x90, 0xe5, 0xdd, 0x2a, 0x91, 0x47, 0xe6, 0xc2, 0xab, + 0x38, 0x1b, 0x5d, 0xe0, 0xa0, 0x65, 0xc8, 0xf1, 0x2f, 0x59, 0xac, 0xc4, 0xa3, 0x4b, 0x24, 0x7c, + 0x1b, 0x66, 0x05, 0x88, 0xf4, 0xec, 0xb8, 0x63, 0xc2, 0x0c, 0x8a, 0x3f, 0x81, 0xb9, 0x30, 0xda, + 0x44, 0x2a, 0x29, 0x42, 0xa6, 0xce, 0x23, 0xe4, 0x9a, 0x14, 0xf2, 0x59, 0xbf, 0xad, 0xa4, 0xbd, + 0xe8, 0xae, 0xab, 0x3b, 0x92, 0x8a, 0xec, 0x88, 0xaf, 0x80, 0x24, 0xf1, 0x8d, 0x2a, 0x30, 0x2b, + 0x8f, 0xc3, 0x8e, 0xe9, 0xfa, 0xc5, 0xd0, 0xc7, 0x80, 0x54, 0xe0, 0x37, 0x2d, 0xd0, 0x06, 0x79, + 0xe1, 0x18, 0x9d, 0x1e, 0xf1, 0x43, 0x3d, 0xad, 0x32, 0x55, 0xe0, 0x44, 0xc1, 0xf1, 0xf7, 0x1a, + 0x94, 0xd6, 0xba, 0x86, 0xd3, 0x93, 0x9b, 0xf5, 0x36, 0x64, 0x79, 0xf9, 0x2a, 0xae, 0x83, 0x77, + 0xc2, 0x64, 0x54, 0x5c, 0x3e, 0x58, 0xe3, 0xc5, 0xae, 0x58, 0x45, 0x37, 0x57, 0x34, 0x6d, 0x37, + 0x22, 0x4d, 0xdc, 0x0d, 0xf4, 0x2a, 0x64, 0x0c, 0xba, 0x84, 0x05, 0x94, 0x4a, 0xf4, 0xe2, 0xc0, + 0xa8, 0xb1, 0x52, 0x83, 0x63, 0xe1, 0x37, 0xa1, 0xa8, 0x70, 0xa0, 0xf7, 0xa1, 0xc7, 0x0d, 0x51, + 0x4e, 0xac, 0xad, 0x1f, 0x6c, 0x3d, 0xe7, 0xd7, 0xa4, 0x0a, 0xc0, 0x46, 0xc3, 0x1f, 0xa7, 0xf0, + 0x07, 0x62, 0x95, 0x08, 0x39, 0xaa, 0x3c, 0x5a, 0x92, 0x3c, 0xa9, 0x73, 0xc9, 0x73, 0x02, 0x65, + 0xa1, 0xfe, 0x44, 0x67, 0xe0, 0x75, 0xc8, 0x32, 0x7a, 0xf2, 0x08, 0xcc, 0xc7, 0xb0, 0x95, 0xd1, + 0x82, 0x23, 0xe2, 0x19, 0x28, 0xef, 0x7b, 0x86, 0x37, 0x70, 0xe5, 0x11, 0xf8, 0x9d, 0x06, 0x15, + 0x09, 0x99, 0xb4, 0x73, 0x24, 0x6f, 0xdc, 0x3c, 0x08, 0xfb, 0xf7, 0xed, 0x4b, 0x90, 0x6d, 0x1f, + 0xee, 0x9b, 0x1f, 0xcb, 0x2e, 0x9f, 0x18, 0x51, 0x78, 0x97, 0xf3, 0xe1, 0xad, 0x76, 0x31, 0xa2, + 0xd7, 0x33, 0xc7, 0x78, 0xe1, 0x6d, 0x59, 0x6d, 0x72, 0xc2, 0xaa, 0xa0, 0x69, 0x3d, 0x00, 0xb0, + 0x1b, 0x95, 0x68, 0xc9, 0xb3, 0xd2, 0x47, 0x6d, 0xd1, 0xcf, 0xc2, 0x85, 0xb5, 0x81, 0x77, 0xd4, + 0xb0, 0x8c, 0xc3, 0xae, 0x0c, 0x1a, 0x78, 0x0e, 0x10, 0x05, 0x6e, 0x98, 0xae, 0x0a, 0x6d, 0xc0, + 0x2c, 0x85, 0x12, 0xcb, 0x33, 0x5b, 0x4a, 0x84, 0x91, 0x79, 0x44, 0x8b, 0xe4, 0x11, 0xc3, 0x75, + 0x5f, 0xda, 0x4e, 0x5b, 0xa8, 0xe6, 0x8f, 0xf1, 0x06, 0x27, 0xfe, 0xcc, 0x0d, 0x65, 0x8a, 0xaf, + 0x4a, 0x65, 0x29, 0xa0, 0xf2, 0x98, 0x78, 0x63, 0xa8, 0xe0, 0x07, 0x70, 0x51, 0x62, 0x8a, 0x96, + 0xcc, 0x18, 0xe4, 0x3d, 0xb8, 0x26, 0x91, 0xd7, 0x8f, 0xe8, 0x5d, 0xe0, 0xa9, 0x60, 0xf8, 0xaf, + 0xca, 0xf9, 0x08, 0x6a, 0xbe, 0x9c, 0xac, 0xf4, 0xb3, 0xbb, 0xaa, 0x00, 0x03, 0x57, 0x9c, 0x99, + 0x82, 0xce, 0xbe, 0x29, 0xcc, 0xb1, 0xbb, 0x7e, 0x56, 0xa6, 0xdf, 0x78, 0x1d, 0xe6, 0x25, 0x0d, + 0x51, 0x94, 0x85, 0x89, 0x8c, 0x08, 0x14, 0x47, 0x44, 0x18, 0x8c, 0x2e, 0x1d, 0x6f, 0x76, 0x15, + 0x33, 0x6c, 0x5a, 0x46, 0x53, 0x53, 0x68, 0x5e, 0xe4, 0x27, 0x82, 0x0a, 0xa6, 0x06, 0x6d, 0x01, + 0xa6, 0x04, 0x54, 0xb0, 0xd8, 0x08, 0x0a, 0x1e, 0xd9, 0x88, 0x11, 0xd2, 0x1f, 0xc2, 0x82, 0x2f, + 0x04, 0xb5, 0xdb, 0x53, 0xe2, 0xf4, 0x4c, 0xd7, 0x55, 0xfa, 0x04, 0x71, 0x8a, 0xdf, 0x81, 0xe9, + 0x3e, 0x11, 0x31, 0xa5, 0xb8, 0x8a, 0x96, 0xf9, 0xc3, 0xd9, 0xb2, 0xb2, 0x98, 0xcd, 0xe3, 0x36, + 0x5c, 0x97, 0xd4, 0xb9, 0x45, 0x63, 0xc9, 0x47, 0x85, 0x92, 0x77, 0x48, 0x6e, 0xd6, 0xd1, 0x3b, + 0x64, 0x9a, 0xef, 0xbd, 0xdf, 0xb0, 0x7a, 0x97, 0x1b, 0x52, 0xfa, 0xd6, 0x44, 0xb9, 0x62, 0x9b, + 0xdb, 0xd4, 0x77, 0xc9, 0x89, 0x88, 0x1d, 0xc2, 0x5c, 0xd8, 0x93, 0x27, 0x0a, 0x63, 0x73, 0x90, + 0xf1, 0xec, 0x63, 0x22, 0x83, 0x18, 0x1f, 0x48, 0x81, 0x7d, 0x37, 0x9f, 0x48, 0x60, 0x23, 0x20, + 0xc6, 0x8e, 0xe4, 0xa4, 0xf2, 0xd2, 0xdd, 0x94, 0xf5, 0x0f, 0x1f, 0xe0, 0x5d, 0xb8, 0x14, 0x0d, + 0x13, 0x13, 0x89, 0xfc, 0x9c, 0x1f, 0xe0, 0xb8, 0x48, 0x32, 0x11, 0xdd, 0xf7, 0x82, 0x60, 0xa0, + 0x04, 0x94, 0x89, 0x48, 0xea, 0x50, 0x8f, 0x8b, 0x2f, 0xff, 0x8e, 0xf3, 0xea, 0x87, 0x9b, 0x89, + 0x88, 0xb9, 0x01, 0xb1, 0xc9, 0xb7, 0x3f, 0x88, 0x11, 0xe9, 0xb1, 0x31, 0x42, 0x38, 0x49, 0x10, + 0xc5, 0xbe, 0x86, 0x43, 0x27, 0x78, 0x04, 0x01, 0x74, 0x52, 0x1e, 0x34, 0x87, 0xf8, 0x3c, 0xd8, + 0x40, 0x1e, 0x6c, 0x35, 0xec, 0x4e, 0xb4, 0x19, 0xef, 0x07, 0xb1, 0x73, 0x24, 0x32, 0x4f, 0x44, + 0xf8, 0x03, 0x58, 0x4c, 0x0e, 0xca, 0x93, 0x50, 0xbe, 0x8f, 0xa1, 0xe0, 0x17, 0x94, 0xca, 0xa3, + 0x73, 0x11, 0x72, 0xbb, 0x7b, 0xfb, 0x4f, 0xd7, 0xd6, 0x1b, 0x55, 0x6d, 0xf5, 0xef, 0x69, 0x48, + 0x6d, 0x3f, 0x47, 0xff, 0x0b, 0x19, 0xfe, 0x96, 0x34, 0xe6, 0xa9, 0xad, 0x3e, 0xee, 0x55, 0x0a, + 0x5f, 0xfd, 0xf4, 0x8f, 0x7f, 0xf9, 0x22, 0x75, 0x09, 0x5f, 0x58, 0x19, 0xbe, 0x61, 0x74, 0xfb, + 0x47, 0xc6, 0xca, 0xf1, 0x70, 0x85, 0xe5, 0x84, 0x87, 0xda, 0x7d, 0xf4, 0x1c, 0xd2, 0x4f, 0x07, + 0x1e, 0x4a, 0x7c, 0x87, 0xab, 0x27, 0xbf, 0x56, 0xe1, 0x3a, 0xa3, 0x3c, 0x87, 0x67, 0x54, 0xca, + 0xfd, 0x81, 0x47, 0xe9, 0x0e, 0xa1, 0xa8, 0x3c, 0x38, 0xa1, 0x33, 0x5f, 0xe8, 0xea, 0x67, 0x3f, + 0x66, 0x61, 0xcc, 0xf8, 0x5d, 0xc5, 0x97, 0x55, 0x7e, 0xfc, 0x5d, 0x4c, 0xd5, 0xe7, 0xe0, 0xc4, + 0x8a, 0xea, 0x13, 0x3c, 0x8b, 0x44, 0xf5, 0x51, 0x9e, 0x22, 0xe2, 0xf5, 0xf1, 0x4e, 0x2c, 0x4a, + 0xd7, 0x16, 0x8f, 0x64, 0x2d, 0x0f, 0x5d, 0x8f, 0x79, 0x47, 0x51, 0x5f, 0x0c, 0xea, 0x8b, 0xc9, + 0x08, 0x82, 0xd3, 0x0d, 0xc6, 0xe9, 0x0a, 0xbe, 0xa4, 0x72, 0x6a, 0xf9, 0x78, 0x0f, 0xb5, 0xfb, + 0xab, 0x47, 0x90, 0x61, 0x7d, 0x4e, 0xd4, 0x94, 0x1f, 0xf5, 0x98, 0x0e, 0x6d, 0xc2, 0x09, 0x08, + 0x75, 0x48, 0xf1, 0x3c, 0xe3, 0x36, 0x8b, 0x2b, 0x3e, 0x37, 0xd6, 0xea, 0x7c, 0xa8, 0xdd, 0x5f, + 0xd2, 0x5e, 0xd3, 0x56, 0xbf, 0x3d, 0x0d, 0x19, 0xd6, 0x3a, 0x42, 0x7d, 0x80, 0xa0, 0x29, 0x18, + 0xd5, 0x73, 0xa4, 0xcd, 0x18, 0xd5, 0x73, 0xb4, 0x9f, 0x88, 0xaf, 0x33, 0xce, 0xf3, 0x78, 0xce, + 0xe7, 0xcc, 0x9e, 0xf4, 0x57, 0x58, 0x93, 0x88, 0x9a, 0xf5, 0x25, 0x14, 0x95, 0xe6, 0x1e, 0x8a, + 0xa3, 0x18, 0xea, 0x0e, 0x46, 0x8f, 0x49, 0x4c, 0x67, 0x10, 0xdf, 0x64, 0x4c, 0xaf, 0xe1, 0x9a, + 0x6a, 0x5c, 0xce, 0xd7, 0x61, 0x98, 0x94, 0xf1, 0x67, 0x1a, 0x54, 0xc2, 0x0d, 0x3e, 0x74, 0x33, + 0x86, 0x74, 0xb4, 0x4f, 0x58, 0xbf, 0x35, 0x1e, 0x29, 0x51, 0x04, 0xce, 0xff, 0x98, 0x90, 0xbe, + 0x41, 0x31, 0x85, 0xed, 0xd1, 0x77, 0x34, 0x98, 0x89, 0xb4, 0xed, 0x50, 0x1c, 0x8b, 0x91, 0xa6, + 0x60, 0xfd, 0xf6, 0x19, 0x58, 0x42, 0x92, 0xbb, 0x4c, 0x92, 0x1b, 0xf8, 0xea, 0xa8, 0x31, 0x3c, + 0xb3, 0x47, 0x3c, 0x5b, 0x48, 0xb3, 0xfa, 0x8f, 0x34, 0xe4, 0xd6, 0xf9, 0xef, 0xaf, 0x90, 0x07, + 0x05, 0xbf, 0x13, 0x86, 0x16, 0xe2, 0xba, 0x12, 0x41, 0xc9, 0x5e, 0xbf, 0x9e, 0x38, 0x2f, 0x44, + 0xb8, 0xc3, 0x44, 0x58, 0xc4, 0x57, 0x7c, 0x11, 0xc4, 0xef, 0xbc, 0x56, 0xf8, 0xe5, 0x7b, 0xc5, + 0x68, 0xb7, 0xe9, 0x96, 0x7c, 0x4b, 0x83, 0x92, 0xda, 0xb0, 0x42, 0x37, 0x62, 0xfb, 0x21, 0x6a, + 0xcf, 0xab, 0x8e, 0xc7, 0xa1, 0x08, 0xfe, 0xf7, 0x18, 0xff, 0x9b, 0x78, 0x21, 0x89, 0xbf, 0xc3, + 0xf0, 0xc3, 0x22, 0xf0, 0x96, 0x53, 0xbc, 0x08, 0xa1, 0x8e, 0x56, 0xbc, 0x08, 0xe1, 0x8e, 0xd5, + 0xd9, 0x22, 0x0c, 0x18, 0x3e, 0x15, 0xe1, 0x04, 0x20, 0xe8, 0x30, 0xa1, 0x58, 0xe3, 0x2a, 0x97, + 0x98, 0xa8, 0x0f, 0x8e, 0x36, 0xa7, 0x62, 0x4e, 0x40, 0x84, 0x77, 0xd7, 0x74, 0xa9, 0x2f, 0xae, + 0xfe, 0x7a, 0x1a, 0x8a, 0x4f, 0x0c, 0xd3, 0xf2, 0x88, 0x65, 0x58, 0x2d, 0x82, 0x3a, 0x90, 0x61, + 0x59, 0x2a, 0x1a, 0x78, 0xd4, 0xb6, 0x4f, 0x34, 0xf0, 0x84, 0x7a, 0x22, 0xf8, 0x36, 0x63, 0x7d, + 0x1d, 0xd7, 0x7d, 0xd6, 0xbd, 0x80, 0xfe, 0x0a, 0xeb, 0x67, 0x50, 0x95, 0x8f, 0x21, 0xcb, 0xfb, + 0x17, 0x28, 0x42, 0x2d, 0xd4, 0xe7, 0xa8, 0x5f, 0x8d, 0x9f, 0x4c, 0x3c, 0x65, 0x2a, 0x2f, 0x97, + 0x21, 0x53, 0x66, 0xff, 0x07, 0x10, 0x34, 0xcc, 0xa2, 0xf6, 0x1d, 0xe9, 0xaf, 0xd5, 0x17, 0x93, + 0x11, 0x04, 0xe3, 0xfb, 0x8c, 0xf1, 0x2d, 0x7c, 0x3d, 0x96, 0x71, 0xdb, 0x5f, 0x40, 0x99, 0xb7, + 0x60, 0x7a, 0xd3, 0x70, 0x8f, 0x50, 0x24, 0x09, 0x29, 0x6f, 0xbb, 0xf5, 0x7a, 0xdc, 0x94, 0x60, + 0x75, 0x8b, 0xb1, 0x5a, 0xc0, 0xf3, 0xb1, 0xac, 0x8e, 0x0c, 0x97, 0xc6, 0x74, 0x34, 0x80, 0xbc, + 0x7c, 0xaf, 0x45, 0xd7, 0x22, 0x36, 0x0b, 0xbf, 0xed, 0xd6, 0x17, 0x92, 0xa6, 0x05, 0xc3, 0x25, + 0xc6, 0x10, 0xe3, 0x6b, 0xf1, 0x46, 0x15, 0xe8, 0x0f, 0xb5, 0xfb, 0xaf, 0x69, 0xab, 0xdf, 0xab, + 0xc2, 0x34, 0xad, 0x97, 0x68, 0x16, 0x09, 0xae, 0x99, 0x51, 0x0b, 0x8f, 0x34, 0x77, 0xa2, 0x16, + 0x1e, 0xbd, 0xa1, 0xc6, 0x64, 0x11, 0xf6, 0x2b, 0x54, 0xc2, 0xb0, 0xa8, 0xc6, 0x1e, 0x14, 0x95, + 0xcb, 0x28, 0x8a, 0xa1, 0x18, 0x6e, 0x1d, 0x45, 0xb3, 0x48, 0xcc, 0x4d, 0x16, 0x2f, 0x32, 0xa6, + 0x75, 0x7c, 0x31, 0xcc, 0xb4, 0xcd, 0xd1, 0x28, 0xd7, 0x4f, 0xa0, 0xa4, 0xde, 0x5a, 0x51, 0x0c, + 0xd1, 0x48, 0x6f, 0x2a, 0x1a, 0x2b, 0xe2, 0x2e, 0xbd, 0x31, 0x4e, 0xe3, 0xff, 0xe6, 0x56, 0xe2, + 0x52, 0xee, 0x1f, 0x41, 0x4e, 0xdc, 0x65, 0xe3, 0xf4, 0x0d, 0x77, 0xb3, 0xe2, 0xf4, 0x8d, 0x5c, + 0x84, 0x63, 0x4a, 0x12, 0xc6, 0x96, 0xd6, 0xec, 0x32, 0x40, 0x0b, 0x96, 0x8f, 0x89, 0x97, 0xc4, + 0x32, 0xe8, 0xcf, 0x24, 0xb1, 0x54, 0xee, 0x4b, 0x63, 0x59, 0x76, 0x88, 0x27, 0xce, 0xb2, 0xbc, + 0x8c, 0xa0, 0x04, 0x8a, 0x6a, 0x34, 0xc4, 0xe3, 0x50, 0x12, 0xab, 0xc8, 0x80, 0xab, 0x08, 0x85, + 0xe8, 0xff, 0x01, 0x82, 0x8b, 0x77, 0xb4, 0x30, 0x88, 0xed, 0xde, 0x45, 0x0b, 0x83, 0xf8, 0xbb, + 0x7b, 0x8c, 0x07, 0x07, 0xcc, 0x79, 0x25, 0x4b, 0xd9, 0xff, 0x50, 0x03, 0x34, 0x7a, 0x51, 0x47, + 0x0f, 0xe2, 0x59, 0xc4, 0x36, 0x06, 0xeb, 0xaf, 0x9c, 0x0f, 0x39, 0x31, 0x7a, 0x06, 0x72, 0xb5, + 0xd8, 0x92, 0xfe, 0x4b, 0x2a, 0xd9, 0xe7, 0x1a, 0x94, 0x43, 0x57, 0x7d, 0x74, 0x27, 0x61, 0x9f, + 0x23, 0xcd, 0xc5, 0xfa, 0xdd, 0x33, 0xf1, 0x12, 0x6b, 0x27, 0xe5, 0x54, 0xc8, 0xba, 0xf1, 0xbb, + 0x1a, 0x54, 0xc2, 0xfd, 0x01, 0x94, 0xc0, 0x60, 0xa4, 0x43, 0x59, 0x5f, 0x3a, 0x1b, 0xf1, 0x1c, + 0xbb, 0x15, 0x94, 0x92, 0x1f, 0x41, 0x4e, 0xb4, 0x15, 0xe2, 0xdc, 0x22, 0xdc, 0xe0, 0x8c, 0x73, + 0x8b, 0x48, 0x4f, 0x22, 0xc9, 0x2d, 0xe8, 0x0d, 0x5d, 0xf1, 0x44, 0xd1, 0x7c, 0x48, 0x62, 0x39, + 0xde, 0x13, 0x23, 0x9d, 0x8b, 0xb1, 0x2c, 0x03, 0x4f, 0x94, 0xad, 0x07, 0x94, 0x40, 0xf1, 0x0c, + 0x4f, 0x8c, 0x76, 0x2e, 0x92, 0x3c, 0x91, 0x71, 0x55, 0x3c, 0x31, 0xe8, 0x14, 0xc4, 0x79, 0xe2, + 0x48, 0xfb, 0x36, 0xce, 0x13, 0x47, 0x9b, 0x0d, 0x49, 0x7b, 0xcb, 0x98, 0x87, 0x3c, 0x71, 0x36, + 0xa6, 0xb3, 0x80, 0x5e, 0x49, 0xb0, 0x69, 0x6c, 0x6b, 0xb8, 0xfe, 0xea, 0x39, 0xb1, 0xc7, 0x7b, + 0x00, 0xdf, 0x0d, 0xe9, 0x01, 0x3f, 0xd5, 0x60, 0x2e, 0xae, 0x35, 0x81, 0x12, 0x98, 0x25, 0xf4, + 0x95, 0xeb, 0xcb, 0xe7, 0x45, 0x3f, 0x87, 0xdd, 0x7c, 0x9f, 0x78, 0x54, 0xfd, 0xed, 0x97, 0x0b, + 0xda, 0x1f, 0xbe, 0x5c, 0xd0, 0xfe, 0xf4, 0xe5, 0x82, 0xf6, 0xa3, 0x3f, 0x2f, 0x4c, 0x1d, 0x66, + 0xd9, 0x7f, 0x05, 0x79, 0xe3, 0x9f, 0x01, 0x00, 0x00, 0xff, 0xff, 0xe5, 0x0a, 0xcf, 0x02, 0x91, + 0x32, 0x00, 0x00, } diff --git a/etcdserver/etcdserverpb/rpc.proto b/etcdserver/etcdserverpb/rpc.proto index a6cd00ab7c3..d65f36b17e7 100644 --- a/etcdserver/etcdserverpb/rpc.proto +++ b/etcdserver/etcdserverpb/rpc.proto @@ -510,6 +510,10 @@ message Compare { // value is the value of the given key, in bytes. bytes value = 7; } + // range_end compares the given target to all keys in the range [key, range_end). + // See RangeRequest for more details on key ranges. + bytes range_end = 8; + // TODO: fill out with most of the rest of RangeRequest fields when needed. } // From google paxosdb paper: diff --git a/integration/v3_grpc_test.go b/integration/v3_grpc_test.go index 7e1fa6c2ec7..b9c7dbc0758 100644 --- a/integration/v3_grpc_test.go +++ b/integration/v3_grpc_test.go @@ -380,6 +380,95 @@ func TestV3TxnCmpHeaderRev(t *testing.T) { } } +// TestV3TxnRangeCompare tests range comparisons in txns +func TestV3TxnRangeCompare(t *testing.T) { + defer testutil.AfterTest(t) + clus := NewClusterV3(t, &ClusterConfig{Size: 1}) + defer clus.Terminate(t) + + // put keys, named by expected revision + for _, k := range []string{"/a/2", "/a/3", "/a/4", "/f/5"} { + if _, err := clus.Client(0).Put(context.TODO(), k, "x"); err != nil { + t.Fatal(err) + } + } + + tests := []struct { + cmp pb.Compare + + wSuccess bool + }{ + { + // >= /a/; all create revs fit + pb.Compare{ + Key: []byte("/a/"), + RangeEnd: []byte{0}, + Target: pb.Compare_CREATE, + Result: pb.Compare_LESS, + TargetUnion: &pb.Compare_CreateRevision{6}, + }, + true, + }, + { + // >= /a/; one create rev doesn't fit + pb.Compare{ + Key: []byte("/a/"), + RangeEnd: []byte{0}, + Target: pb.Compare_CREATE, + Result: pb.Compare_LESS, + TargetUnion: &pb.Compare_CreateRevision{5}, + }, + false, + }, + { + // prefix /a/*; all create revs fit + pb.Compare{ + Key: []byte("/a/"), + RangeEnd: []byte("/a0"), + Target: pb.Compare_CREATE, + Result: pb.Compare_LESS, + TargetUnion: &pb.Compare_CreateRevision{5}, + }, + true, + }, + { + // prefix /a/*; one create rev doesn't fit + pb.Compare{ + Key: []byte("/a/"), + RangeEnd: []byte("/a0"), + Target: pb.Compare_CREATE, + Result: pb.Compare_LESS, + TargetUnion: &pb.Compare_CreateRevision{4}, + }, + false, + }, + { + // does not exist, does not succeed + pb.Compare{ + Key: []byte("/b/"), + RangeEnd: []byte("/b0"), + Target: pb.Compare_VALUE, + Result: pb.Compare_EQUAL, + TargetUnion: &pb.Compare_Value{[]byte("x")}, + }, + false, + }, + } + + kvc := toGRPC(clus.Client(0)).KV + for i, tt := range tests { + txn := &pb.TxnRequest{} + txn.Compare = append(txn.Compare, &tt.cmp) + tresp, err := kvc.Txn(context.TODO(), txn) + if err != nil { + t.Fatal(err) + } + if tt.wSuccess != tresp.Succeeded { + t.Errorf("#%d: expected %v, got %v", i, tt.wSuccess, tresp.Succeeded) + } + } +} + // TestV3PutIgnoreValue ensures that writes with ignore_value overwrites with previous key-value pair. func TestV3PutIgnoreValue(t *testing.T) { defer testutil.AfterTest(t) diff --git a/proxy/grpcproxy/kv.go b/proxy/grpcproxy/kv.go index 65f850ed426..c68f1b1c5fb 100644 --- a/proxy/grpcproxy/kv.go +++ b/proxy/grpcproxy/kv.go @@ -123,7 +123,7 @@ func (p *kvProxy) Txn(ctx context.Context, r *pb.TxnRequest) (*pb.TxnResponse, e } // txn may claim an outdated key is updated; be safe and invalidate for _, cmp := range r.Compare { - p.cache.Invalidate(cmp.Key, nil) + p.cache.Invalidate(cmp.Key, cmp.RangeEnd) } // update any fetched keys if resp.Succeeded {