Merge pull request #8025 from heyitsanthony/txn-cmp-range

api: txn comparisons on ranges
release-3.3
Anthony Romano 2017-06-18 11:11:43 -07:00 committed by GitHub
commit 45fbac5544
11 changed files with 457 additions and 259 deletions

View File

@ -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 |

View File

@ -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": []
}
]
}
}

View File

@ -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

View File

@ -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")
}
}

View File

@ -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

View File

@ -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 {

View File

@ -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
}
}

View File

@ -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,
}

View File

@ -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:

View File

@ -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)

View File

@ -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 {