Merge pull request #7214 from sinsharat/support_put_ignore_lease

*: 'ignore_lease' to detach value with PutRequest
This commit is contained in:
Xiang Li 2017-01-24 14:53:51 -08:00 committed by GitHub
commit d7cc9be3fd
15 changed files with 544 additions and 238 deletions

View File

@ -617,6 +617,7 @@ Empty field.
| lease | lease is the lease ID to associate with the key in the key-value store. A lease value of 0 indicates no lease. | int64 | | lease | lease is the lease ID to associate with the key in the key-value store. A lease value of 0 indicates no lease. | int64 |
| prev_kv | If prev_kv is set, etcd gets the previous key-value pair before changing it. The previous key-value pair will be returned in the put response. | bool | | prev_kv | If prev_kv is set, etcd gets the previous key-value pair before changing it. The previous key-value pair will be returned in the put response. | bool |
| ignore_value | If ignore_value is set, etcd updates the key using its current value. Returns an error if the key does not exist. | bool | | ignore_value | If ignore_value is set, etcd updates the key using its current value. Returns an error if the key does not exist. | bool |
| ignore_lease | If ignore_lease is set, etcd updates the key using its current lease. Returns an error if the key does not exist. | bool |

View File

@ -1833,6 +1833,11 @@
"type": "boolean", "type": "boolean",
"format": "boolean", "format": "boolean",
"description": "If ignore_value is set, etcd updates the key using its current value.\nReturns an error if the key does not exist." "description": "If ignore_value is set, etcd updates the key using its current value.\nReturns an error if the key does not exist."
},
"ignore_lease": {
"type": "boolean",
"format": "boolean",
"description": "If ignore_lease is set, etcd updates the key using its current lease.\nReturns an error if the key does not exist."
} }
} }
}, },

View File

@ -146,6 +146,47 @@ func TestKVPutWithIgnoreValue(t *testing.T) {
} }
} }
// TestKVPutWithIgnoreLease ensures that Put with WithIgnoreLease does not affect the existing lease for the key.
func TestKVPutWithIgnoreLease(t *testing.T) {
defer testutil.AfterTest(t)
clus := integration.NewClusterV3(t, &integration.ClusterConfig{Size: 1})
defer clus.Terminate(t)
kv := clientv3.NewKV(clus.RandClient())
lapi := clientv3.NewLease(clus.RandClient())
defer lapi.Close()
resp, err := lapi.Grant(context.Background(), 10)
if err != nil {
t.Errorf("failed to create lease %v", err)
}
if _, err := kv.Put(context.TODO(), "zoo", "bar", clientv3.WithIgnoreLease()); err != rpctypes.ErrKeyNotFound {
t.Fatalf("err expected %v, got %v", rpctypes.ErrKeyNotFound, err)
}
if _, err := kv.Put(context.TODO(), "zoo", "bar", clientv3.WithLease(resp.ID)); err != nil {
t.Fatal(err)
}
if _, err := kv.Put(context.TODO(), "zoo", "bar1", clientv3.WithIgnoreLease()); err != nil {
t.Fatal(err)
}
rr, rerr := kv.Get(context.TODO(), "zoo")
if rerr != nil {
t.Fatal(rerr)
}
if len(rr.Kvs) != 1 {
t.Fatalf("len(rr.Kvs) expected 1, got %d", len(rr.Kvs))
}
if rr.Kvs[0].Lease != int64(resp.ID) {
t.Fatalf("lease expected %v, got %v", resp.ID, rr.Kvs[0].Lease)
}
}
func TestKVPutWithRequireLeader(t *testing.T) { func TestKVPutWithRequireLeader(t *testing.T) {
defer testutil.AfterTest(t) defer testutil.AfterTest(t)

View File

@ -148,7 +148,7 @@ func (kv *kv) do(ctx context.Context, op Op) (OpResponse, error) {
} }
case tPut: case tPut:
var resp *pb.PutResponse var resp *pb.PutResponse
r := &pb.PutRequest{Key: op.key, Value: op.val, Lease: int64(op.leaseID), PrevKv: op.prevKV, IgnoreValue: op.ignoreValue} r := &pb.PutRequest{Key: op.key, Value: op.val, Lease: int64(op.leaseID), PrevKv: op.prevKV, IgnoreValue: op.ignoreValue, IgnoreLease: op.ignoreLease}
resp, err = kv.remote.Put(ctx, r) resp, err = kv.remote.Put(ctx, r)
if err == nil { if err == nil {
return OpResponse{put: (*PutResponse)(resp)}, nil return OpResponse{put: (*PutResponse)(resp)}, nil

View File

@ -54,6 +54,7 @@ type Op struct {
// for put // for put
ignoreValue bool ignoreValue bool
ignoreLease bool
// progressNotify is for progress updates. // progressNotify is for progress updates.
progressNotify bool progressNotify bool
@ -97,7 +98,7 @@ func (op Op) toRequestOp() *pb.RequestOp {
case tRange: case tRange:
return &pb.RequestOp{Request: &pb.RequestOp_RequestRange{RequestRange: op.toRangeRequest()}} return &pb.RequestOp{Request: &pb.RequestOp_RequestRange{RequestRange: op.toRangeRequest()}}
case tPut: case tPut:
r := &pb.PutRequest{Key: op.key, Value: op.val, Lease: int64(op.leaseID), PrevKv: op.prevKV, IgnoreValue: op.ignoreValue} r := &pb.PutRequest{Key: op.key, Value: op.val, Lease: int64(op.leaseID), PrevKv: op.prevKV, IgnoreValue: op.ignoreValue, IgnoreLease: op.ignoreLease}
return &pb.RequestOp{Request: &pb.RequestOp_RequestPut{RequestPut: r}} return &pb.RequestOp{Request: &pb.RequestOp_RequestPut{RequestPut: r}}
case tDeleteRange: case tDeleteRange:
r := &pb.DeleteRangeRequest{Key: op.key, RangeEnd: op.end, PrevKv: op.prevKV} r := &pb.DeleteRangeRequest{Key: op.key, RangeEnd: op.end, PrevKv: op.prevKV}
@ -372,6 +373,15 @@ func WithIgnoreValue() OpOption {
} }
} }
// WithIgnoreLease updates the key using its current lease.
// Empty lease should be passed when ignore_lease is set.
// Returns an error if the key does not exist.
func WithIgnoreLease() OpOption {
return func(op *Op) {
op.ignoreLease = true
}
}
// LeaseOp represents an Operation that lease can execute. // LeaseOp represents an Operation that lease can execute.
type LeaseOp struct { type LeaseOp struct {
id LeaseID id LeaseID

View File

@ -29,6 +29,7 @@ func TestCtlV3PutClientTLSFlagByEnv(t *testing.T) {
testCtl(t, putTest, withCfg(configClientTLS), withFlagByEnv()) testCtl(t, putTest, withCfg(configClientTLS), withFlagByEnv())
} }
func TestCtlV3PutIgnoreValue(t *testing.T) { testCtl(t, putTestIgnoreValue) } func TestCtlV3PutIgnoreValue(t *testing.T) { testCtl(t, putTestIgnoreValue) }
func TestCtlV3PutIgnoreLease(t *testing.T) { testCtl(t, putTestIgnoreLease) }
func TestCtlV3Get(t *testing.T) { testCtl(t, getTest) } func TestCtlV3Get(t *testing.T) { testCtl(t, getTest) }
func TestCtlV3GetNoTLS(t *testing.T) { testCtl(t, getTest, withCfg(configNoTLS)) } func TestCtlV3GetNoTLS(t *testing.T) { testCtl(t, getTest, withCfg(configNoTLS)) }
@ -78,6 +79,31 @@ func putTestIgnoreValue(cx ctlCtx) {
} }
} }
func putTestIgnoreLease(cx ctlCtx) {
leaseID, err := ctlV3LeaseGrant(cx, 10)
if err != nil {
cx.t.Fatalf("putTestIgnoreLease: ctlV3LeaseGrant error (%v)", err)
}
if err := ctlV3Put(cx, "foo", "bar", leaseID); err != nil {
cx.t.Fatalf("putTestIgnoreLease: ctlV3Put error (%v)", err)
}
if err := ctlV3Get(cx, []string{"foo"}, kv{"foo", "bar"}); err != nil {
cx.t.Fatalf("putTestIgnoreLease: ctlV3Get error (%v)", err)
}
if err := ctlV3Put(cx, "foo", "bar1", "", "--ignore-lease"); err != nil {
cx.t.Fatalf("putTestIgnoreLease: ctlV3Put error (%v)", err)
}
if err := ctlV3Get(cx, []string{"foo"}, kv{"foo", "bar1"}); err != nil {
cx.t.Fatalf("putTestIgnoreLease: ctlV3Get error (%v)", err)
}
if err := ctlV3LeaseRevoke(cx, leaseID); err != nil {
cx.t.Fatalf("putTestIgnoreLease: ctlV3LeaseRevok error (%v)", err)
}
if err := ctlV3Get(cx, []string{"key"}); err != nil { // expect no output
cx.t.Fatalf("putTestIgnoreLease: ctlV3Get error (%v)", err)
}
}
func getTest(cx ctlCtx) { func getTest(cx ctlCtx) {
var ( var (
kvs = []kv{{"key1", "val1"}, {"key2", "val2"}, {"key3", "val3"}} kvs = []kv{{"key1", "val1"}, {"key2", "val2"}, {"key3", "val3"}}
@ -245,17 +271,20 @@ func delTest(cx ctlCtx) {
func ctlV3Put(cx ctlCtx, key, value, leaseID string, flags ...string) error { func ctlV3Put(cx ctlCtx, key, value, leaseID string, flags ...string) error {
skipValue := false skipValue := false
skipLease := false
for _, f := range flags { for _, f := range flags {
if f == "--ignore-value" { if f == "--ignore-value" {
skipValue = true skipValue = true
break }
if f == "--ignore-lease" {
skipLease = true
} }
} }
cmdArgs := append(cx.PrefixArgs(), "put", key) cmdArgs := append(cx.PrefixArgs(), "put", key)
if !skipValue { if !skipValue {
cmdArgs = append(cmdArgs, value) cmdArgs = append(cmdArgs, value)
} }
if leaseID != "" { if leaseID != "" && !skipLease {
cmdArgs = append(cmdArgs, "--lease", leaseID) cmdArgs = append(cmdArgs, "--lease", leaseID)
} }
if len(flags) != 0 { if len(flags) != 0 {

View File

@ -31,6 +31,8 @@ RPC: Put
- ignore-value -- updates the key using its current value. - ignore-value -- updates the key using its current value.
- ignore-lease -- updates the key using its current lease.
#### Output #### Output
`OK` `OK`
@ -47,6 +49,16 @@ RPC: Put
# OK # OK
``` ```
```bash
./etcdctl put foo bar --lease=1234abcd
# OK
./etcdctl put foo bar1 --ignore-lease # to use existing lease 1234abcd
# OK
./etcdctl get foo
# foo
# bar1
```
```bash ```bash
./etcdctl put foo bar1 --prev-kv ./etcdctl put foo bar1 --prev-kv
# OK # OK

View File

@ -24,9 +24,10 @@ import (
) )
var ( var (
leaseStr string leaseStr string
putPrevKV bool putPrevKV bool
putIgnoreVal bool putIgnoreVal bool
putIgnoreLease bool
) )
// NewPutCommand returns the cobra command for "put". // NewPutCommand returns the cobra command for "put".
@ -46,6 +47,9 @@ $ put -- <key> <value>
If <value> isn't given as a command line argument and '--ignore-value' is not specified, If <value> isn't given as a command line argument and '--ignore-value' is not specified,
this command tries to read the value from standard input. this command tries to read the value from standard input.
If <lease> isn't given as a command line argument and '--ignore-lease' is not specified,
this command tries to read the value from standard input.
For example, For example,
$ cat file | put <key> $ cat file | put <key>
will store the content of the file to <key>. will store the content of the file to <key>.
@ -55,6 +59,7 @@ will store the content of the file to <key>.
cmd.Flags().StringVar(&leaseStr, "lease", "0", "lease ID (in hexadecimal) to attach to the key") cmd.Flags().StringVar(&leaseStr, "lease", "0", "lease ID (in hexadecimal) to attach to the key")
cmd.Flags().BoolVar(&putPrevKV, "prev-kv", false, "return the previous key-value pair before modification") cmd.Flags().BoolVar(&putPrevKV, "prev-kv", false, "return the previous key-value pair before modification")
cmd.Flags().BoolVar(&putIgnoreVal, "ignore-value", false, "updates the key using its current value") cmd.Flags().BoolVar(&putIgnoreVal, "ignore-value", false, "updates the key using its current value")
cmd.Flags().BoolVar(&putIgnoreLease, "ignore-lease", false, "updates the key using its current lease")
return cmd return cmd
} }
@ -80,6 +85,7 @@ func getPutOp(cmd *cobra.Command, args []string) (string, string, []clientv3.OpO
if putIgnoreVal && len(args) > 1 { if putIgnoreVal && len(args) > 1 {
ExitWithError(ExitBadArgs, fmt.Errorf("put command needs only 1 argument when 'ignore-value' is set.")) ExitWithError(ExitBadArgs, fmt.Errorf("put command needs only 1 argument when 'ignore-value' is set."))
} }
var value string var value string
var err error var err error
if !putIgnoreVal { if !putIgnoreVal {
@ -104,6 +110,9 @@ func getPutOp(cmd *cobra.Command, args []string) (string, string, []clientv3.OpO
if putIgnoreVal { if putIgnoreVal {
opts = append(opts, clientv3.WithIgnoreValue()) opts = append(opts, clientv3.WithIgnoreValue())
} }
if putIgnoreLease {
opts = append(opts, clientv3.WithIgnoreLease())
}
return key, value, opts return key, value, opts
} }

View File

@ -135,7 +135,10 @@ func checkPutRequest(r *pb.PutRequest) error {
return rpctypes.ErrGRPCEmptyKey return rpctypes.ErrGRPCEmptyKey
} }
if r.IgnoreValue && len(r.Value) != 0 { if r.IgnoreValue && len(r.Value) != 0 {
return rpctypes.ErrGRPCValue return rpctypes.ErrGRPCValueProvided
}
if r.IgnoreLease && r.Lease != 0 {
return rpctypes.ErrGRPCLeaseProvided
} }
return nil return nil
} }

View File

@ -21,14 +21,15 @@ import (
var ( var (
// server-side error // server-side error
ErrGRPCEmptyKey = grpc.Errorf(codes.InvalidArgument, "etcdserver: key is not provided") ErrGRPCEmptyKey = grpc.Errorf(codes.InvalidArgument, "etcdserver: key is not provided")
ErrGRPCKeyNotFound = grpc.Errorf(codes.InvalidArgument, "etcdserver: key not found") ErrGRPCKeyNotFound = grpc.Errorf(codes.InvalidArgument, "etcdserver: key not found")
ErrGRPCValue = grpc.Errorf(codes.InvalidArgument, "etcdserver: value is provided") ErrGRPCValueProvided = grpc.Errorf(codes.InvalidArgument, "etcdserver: value is provided")
ErrGRPCTooManyOps = grpc.Errorf(codes.InvalidArgument, "etcdserver: too many operations in txn request") ErrGRPCLeaseProvided = grpc.Errorf(codes.InvalidArgument, "etcdserver: lease is provided")
ErrGRPCDuplicateKey = grpc.Errorf(codes.InvalidArgument, "etcdserver: duplicate key given in txn request") ErrGRPCTooManyOps = grpc.Errorf(codes.InvalidArgument, "etcdserver: too many operations in txn request")
ErrGRPCCompacted = grpc.Errorf(codes.OutOfRange, "etcdserver: mvcc: required revision has been compacted") ErrGRPCDuplicateKey = grpc.Errorf(codes.InvalidArgument, "etcdserver: duplicate key given in txn request")
ErrGRPCFutureRev = grpc.Errorf(codes.OutOfRange, "etcdserver: mvcc: required revision is a future revision") ErrGRPCCompacted = grpc.Errorf(codes.OutOfRange, "etcdserver: mvcc: required revision has been compacted")
ErrGRPCNoSpace = grpc.Errorf(codes.ResourceExhausted, "etcdserver: mvcc: database space exceeded") ErrGRPCFutureRev = grpc.Errorf(codes.OutOfRange, "etcdserver: mvcc: required revision is a future revision")
ErrGRPCNoSpace = grpc.Errorf(codes.ResourceExhausted, "etcdserver: mvcc: database space exceeded")
ErrGRPCLeaseNotFound = grpc.Errorf(codes.NotFound, "etcdserver: requested lease not found") ErrGRPCLeaseNotFound = grpc.Errorf(codes.NotFound, "etcdserver: requested lease not found")
ErrGRPCLeaseExist = grpc.Errorf(codes.FailedPrecondition, "etcdserver: lease already exists") ErrGRPCLeaseExist = grpc.Errorf(codes.FailedPrecondition, "etcdserver: lease already exists")
@ -65,9 +66,11 @@ var (
ErrGRPCUnhealthy = grpc.Errorf(codes.Unavailable, "etcdserver: unhealthy cluster") ErrGRPCUnhealthy = grpc.Errorf(codes.Unavailable, "etcdserver: unhealthy cluster")
errStringToError = map[string]error{ errStringToError = map[string]error{
grpc.ErrorDesc(ErrGRPCEmptyKey): ErrGRPCEmptyKey, grpc.ErrorDesc(ErrGRPCEmptyKey): ErrGRPCEmptyKey,
grpc.ErrorDesc(ErrGRPCKeyNotFound): ErrGRPCKeyNotFound, grpc.ErrorDesc(ErrGRPCKeyNotFound): ErrGRPCKeyNotFound,
grpc.ErrorDesc(ErrGRPCValue): ErrGRPCValue, grpc.ErrorDesc(ErrGRPCValueProvided): ErrGRPCValueProvided,
grpc.ErrorDesc(ErrGRPCLeaseProvided): ErrGRPCLeaseProvided,
grpc.ErrorDesc(ErrGRPCTooManyOps): ErrGRPCTooManyOps, grpc.ErrorDesc(ErrGRPCTooManyOps): ErrGRPCTooManyOps,
grpc.ErrorDesc(ErrGRPCDuplicateKey): ErrGRPCDuplicateKey, grpc.ErrorDesc(ErrGRPCDuplicateKey): ErrGRPCDuplicateKey,
grpc.ErrorDesc(ErrGRPCCompacted): ErrGRPCCompacted, grpc.ErrorDesc(ErrGRPCCompacted): ErrGRPCCompacted,
@ -110,14 +113,15 @@ var (
} }
// client-side error // client-side error
ErrEmptyKey = Error(ErrGRPCEmptyKey) ErrEmptyKey = Error(ErrGRPCEmptyKey)
ErrKeyNotFound = Error(ErrGRPCKeyNotFound) ErrKeyNotFound = Error(ErrGRPCKeyNotFound)
ErrValue = Error(ErrGRPCValue) ErrValueProvided = Error(ErrGRPCValueProvided)
ErrTooManyOps = Error(ErrGRPCTooManyOps) ErrLeaseProvided = Error(ErrGRPCLeaseProvided)
ErrDuplicateKey = Error(ErrGRPCDuplicateKey) ErrTooManyOps = Error(ErrGRPCTooManyOps)
ErrCompacted = Error(ErrGRPCCompacted) ErrDuplicateKey = Error(ErrGRPCDuplicateKey)
ErrFutureRev = Error(ErrGRPCFutureRev) ErrCompacted = Error(ErrGRPCCompacted)
ErrNoSpace = Error(ErrGRPCNoSpace) ErrFutureRev = Error(ErrGRPCFutureRev)
ErrNoSpace = Error(ErrGRPCNoSpace)
ErrLeaseNotFound = Error(ErrGRPCLeaseNotFound) ErrLeaseNotFound = Error(ErrGRPCLeaseNotFound)
ErrLeaseExist = Error(ErrGRPCLeaseExist) ErrLeaseExist = Error(ErrGRPCLeaseExist)

View File

@ -161,7 +161,7 @@ func (a *applierV3backend) Put(txnID int64, p *pb.PutRequest) (*pb.PutResponse,
) )
var rr *mvcc.RangeResult var rr *mvcc.RangeResult
if p.PrevKv || p.IgnoreValue { if p.PrevKv || p.IgnoreValue || p.IgnoreLease {
if txnID != noTxn { if txnID != noTxn {
rr, err = a.s.KV().TxnRange(txnID, p.Key, nil, mvcc.RangeOptions{}) rr, err = a.s.KV().TxnRange(txnID, p.Key, nil, mvcc.RangeOptions{})
if err != nil { if err != nil {
@ -183,6 +183,14 @@ func (a *applierV3backend) Put(txnID int64, p *pb.PutRequest) (*pb.PutResponse,
p.Value = rr.KVs[0].Value p.Value = rr.KVs[0].Value
} }
if p.IgnoreLease {
if rr == nil || len(rr.KVs) == 0 {
// ignore_lease flag expects previous key-value pair
return nil, ErrKeyNotFound
}
p.Lease = rr.KVs[0].Lease
}
if txnID != noTxn { if txnID != noTxn {
rev, err = a.s.KV().TxnPut(txnID, p.Key, p.Value, lease.LeaseID(p.Lease)) rev, err = a.s.KV().TxnPut(txnID, p.Key, p.Value, lease.LeaseID(p.Lease))
if err != nil { if err != nil {
@ -767,7 +775,7 @@ func (a *applierV3backend) checkRequestPut(reqs []*pb.RequestOp) error {
if preq == nil { if preq == nil {
continue continue
} }
if preq.IgnoreValue { if preq.IgnoreValue || preq.IgnoreLease {
// expects previous key-value, error if not exist // expects previous key-value, error if not exist
rr, err := a.s.KV().Range(preq.Key, nil, mvcc.RangeOptions{}) rr, err := a.s.KV().Range(preq.Key, nil, mvcc.RangeOptions{})
if err != nil { if err != nil {

View File

@ -316,6 +316,9 @@ type PutRequest struct {
// If ignore_value is set, etcd updates the key using its current value. // If ignore_value is set, etcd updates the key using its current value.
// Returns an error if the key does not exist. // Returns an error if the key does not exist.
IgnoreValue bool `protobuf:"varint,5,opt,name=ignore_value,json=ignoreValue,proto3" json:"ignore_value,omitempty"` IgnoreValue bool `protobuf:"varint,5,opt,name=ignore_value,json=ignoreValue,proto3" json:"ignore_value,omitempty"`
// If ignore_lease is set, etcd updates the key using its current lease.
// Returns an error if the key does not exist.
IgnoreLease bool `protobuf:"varint,6,opt,name=ignore_lease,json=ignoreLease,proto3" json:"ignore_lease,omitempty"`
} }
func (m *PutRequest) Reset() { *m = PutRequest{} } func (m *PutRequest) Reset() { *m = PutRequest{} }
@ -3954,6 +3957,16 @@ func (m *PutRequest) MarshalTo(dAtA []byte) (int, error) {
} }
i++ i++
} }
if m.IgnoreLease {
dAtA[i] = 0x30
i++
if m.IgnoreLease {
dAtA[i] = 1
} else {
dAtA[i] = 0
}
i++
}
return i, nil return i, nil
} }
@ -6626,6 +6639,9 @@ func (m *PutRequest) Size() (n int) {
if m.IgnoreValue { if m.IgnoreValue {
n += 2 n += 2
} }
if m.IgnoreLease {
n += 2
}
return n return n
} }
@ -8449,6 +8465,26 @@ func (m *PutRequest) Unmarshal(dAtA []byte) error {
} }
} }
m.IgnoreValue = bool(v != 0) m.IgnoreValue = bool(v != 0)
case 6:
if wireType != 0 {
return fmt.Errorf("proto: wrong wireType = %d for field IgnoreLease", wireType)
}
var v int
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowRpc
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
v |= (int(b) & 0x7F) << shift
if b < 0x80 {
break
}
}
m.IgnoreLease = bool(v != 0)
default: default:
iNdEx = preIndex iNdEx = preIndex
skippy, err := skipRpc(dAtA[iNdEx:]) skippy, err := skipRpc(dAtA[iNdEx:])
@ -16077,219 +16113,220 @@ var (
func init() { proto.RegisterFile("rpc.proto", fileDescriptorRpc) } func init() { proto.RegisterFile("rpc.proto", fileDescriptorRpc) }
var fileDescriptorRpc = []byte{ var fileDescriptorRpc = []byte{
// 3423 bytes of a gzipped FileDescriptorProto // 3431 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0xb4, 0x5b, 0xcd, 0x73, 0x1b, 0xc7, 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0xb4, 0x5b, 0xcd, 0x73, 0x1b, 0xc7,
0xb1, 0xe7, 0x02, 0x04, 0x40, 0x34, 0x3e, 0x08, 0x0d, 0x29, 0x09, 0x84, 0x24, 0x8a, 0x1a, 0x7d, 0xb1, 0xe7, 0x02, 0x04, 0x40, 0x34, 0x3e, 0x08, 0x0d, 0x29, 0x09, 0x84, 0x24, 0x8a, 0x1a, 0x7d,
0x51, 0x92, 0x4d, 0xda, 0xb4, 0xdf, 0x3b, 0xe8, 0xb9, 0x5c, 0x8f, 0x22, 0x61, 0x91, 0x8f, 0x14, 0x51, 0x92, 0x4d, 0xda, 0xb4, 0xdf, 0x3b, 0xe8, 0xb9, 0x5c, 0x8f, 0x22, 0x61, 0x91, 0x8f, 0x14,
0x29, 0x2f, 0x29, 0xd9, 0xaf, 0xca, 0x15, 0xd4, 0x12, 0x18, 0x81, 0x5b, 0x04, 0x76, 0xe1, 0xdd, 0x29, 0x2f, 0x29, 0xd9, 0xaf, 0xca, 0x15, 0xd4, 0x12, 0x18, 0x81, 0x5b, 0x04, 0x76, 0xe1, 0xdd,
0x05, 0x44, 0x3a, 0x49, 0x55, 0xca, 0xb1, 0x93, 0x4a, 0x8e, 0xf1, 0x21, 0x5f, 0xc7, 0x54, 0x0e, 0x05, 0x44, 0x3a, 0x49, 0x55, 0xca, 0xb1, 0x2b, 0x95, 0x1c, 0xe3, 0x43, 0xbe, 0x8e, 0xa9, 0x1c,
0xf9, 0x03, 0x72, 0xcb, 0x1f, 0x90, 0xca, 0x25, 0xa9, 0xca, 0x3f, 0x90, 0x72, 0x72, 0xc8, 0x21, 0xfc, 0x07, 0xe4, 0x96, 0x3f, 0x20, 0x95, 0x4b, 0x52, 0x95, 0x7f, 0x20, 0xe5, 0xe4, 0x90, 0x43,
0xf7, 0x9c, 0x52, 0x49, 0xcd, 0xd7, 0xee, 0xec, 0x62, 0x17, 0x94, 0xb3, 0xf1, 0x45, 0xdc, 0xe9, 0xee, 0x39, 0xa5, 0x92, 0x9a, 0xaf, 0xdd, 0xd9, 0xc5, 0x2e, 0x28, 0x67, 0xe3, 0x8b, 0xb8, 0xd3,
0xe9, 0xe9, 0x5f, 0x4f, 0xcf, 0x74, 0x4f, 0x4f, 0x0f, 0x04, 0x45, 0x67, 0xd0, 0x5e, 0x19, 0x38, 0xd3, 0xd3, 0xbf, 0x9e, 0x9e, 0xe9, 0x9e, 0x9e, 0x1e, 0x08, 0x8a, 0xce, 0xa0, 0xbd, 0x32, 0x70,
0xb6, 0x67, 0xa3, 0x32, 0xf1, 0xda, 0x1d, 0x97, 0x38, 0x23, 0xe2, 0x0c, 0x8e, 0x1a, 0xf3, 0x5d, 0x6c, 0xcf, 0x46, 0x65, 0xe2, 0xb5, 0x3b, 0x2e, 0x71, 0x46, 0xc4, 0x19, 0x1c, 0x35, 0xe6, 0xbb,
0xbb, 0x6b, 0xb3, 0x8e, 0x55, 0xfa, 0xc5, 0x79, 0x1a, 0x0b, 0x94, 0x67, 0xb5, 0x3f, 0x6a, 0xb7, 0x76, 0xd7, 0x66, 0x1d, 0xab, 0xf4, 0x8b, 0xf3, 0x34, 0x16, 0x28, 0xcf, 0x6a, 0x7f, 0xd4, 0x6e,
0xd9, 0x3f, 0x83, 0xa3, 0xd5, 0x93, 0x91, 0xe8, 0xba, 0xc2, 0xba, 0x8c, 0xa1, 0x77, 0xcc, 0xfe, 0xb3, 0x7f, 0x06, 0x47, 0xab, 0x27, 0x23, 0xd1, 0x75, 0x85, 0x75, 0x19, 0x43, 0xef, 0x98, 0xfd,
0x19, 0x1c, 0xb1, 0x3f, 0xa2, 0xf3, 0x6a, 0xd7, 0xb6, 0xbb, 0x3d, 0xb2, 0x6a, 0x0c, 0xcc, 0x55, 0x33, 0x38, 0x62, 0x7f, 0x44, 0xe7, 0xd5, 0xae, 0x6d, 0x77, 0x7b, 0x64, 0xd5, 0x18, 0x98, 0xab,
0xc3, 0xb2, 0x6c, 0xcf, 0xf0, 0x4c, 0xdb, 0x72, 0x79, 0x2f, 0xfe, 0x5c, 0x83, 0xaa, 0x4e, 0xdc, 0x86, 0x65, 0xd9, 0x9e, 0xe1, 0x99, 0xb6, 0xe5, 0xf2, 0x5e, 0xfc, 0xb9, 0x06, 0x55, 0x9d, 0xb8,
0x81, 0x6d, 0xb9, 0x64, 0x8b, 0x18, 0x1d, 0xe2, 0xa0, 0x6b, 0x00, 0xed, 0xde, 0xd0, 0xf5, 0x88, 0x03, 0xdb, 0x72, 0xc9, 0x16, 0x31, 0x3a, 0xc4, 0x41, 0xd7, 0x00, 0xda, 0xbd, 0xa1, 0xeb, 0x11,
0xd3, 0x32, 0x3b, 0x75, 0x6d, 0x49, 0x5b, 0x9e, 0xd6, 0x8b, 0x82, 0xb2, 0xdd, 0x41, 0x57, 0xa0, 0xa7, 0x65, 0x76, 0xea, 0xda, 0x92, 0xb6, 0x3c, 0xad, 0x17, 0x05, 0x65, 0xbb, 0x83, 0xae, 0x40,
0xd8, 0x27, 0xfd, 0x23, 0xde, 0x9b, 0x61, 0xbd, 0x33, 0x9c, 0xb0, 0xdd, 0x41, 0x0d, 0x98, 0x71, 0xb1, 0x4f, 0xfa, 0x47, 0xbc, 0x37, 0xc3, 0x7a, 0x67, 0x38, 0x61, 0xbb, 0x83, 0x1a, 0x30, 0xe3,
0xc8, 0xc8, 0x74, 0x4d, 0xdb, 0xaa, 0x67, 0x97, 0xb4, 0xe5, 0xac, 0xee, 0xb7, 0xe9, 0x40, 0xc7, 0x90, 0x91, 0xe9, 0x9a, 0xb6, 0x55, 0xcf, 0x2e, 0x69, 0xcb, 0x59, 0xdd, 0x6f, 0xd3, 0x81, 0x8e,
0x78, 0xe1, 0xb5, 0x3c, 0xe2, 0xf4, 0xeb, 0xd3, 0x7c, 0x20, 0x25, 0x1c, 0x12, 0xa7, 0x8f, 0x3f, 0xf1, 0xc2, 0x6b, 0x79, 0xc4, 0xe9, 0xd7, 0xa7, 0xf9, 0x40, 0x4a, 0x38, 0x24, 0x4e, 0x1f, 0x7f,
0xcb, 0x41, 0x59, 0x37, 0xac, 0x2e, 0xd1, 0xc9, 0xc7, 0x43, 0xe2, 0x7a, 0xa8, 0x06, 0xd9, 0x13, 0x96, 0x83, 0xb2, 0x6e, 0x58, 0x5d, 0xa2, 0x93, 0x8f, 0x87, 0xc4, 0xf5, 0x50, 0x0d, 0xb2, 0x27,
0x72, 0xc6, 0xe0, 0xcb, 0x3a, 0xfd, 0xe4, 0xe3, 0xad, 0x2e, 0x69, 0x11, 0x8b, 0x03, 0x97, 0xe9, 0xe4, 0x8c, 0xc1, 0x97, 0x75, 0xfa, 0xc9, 0xc7, 0x5b, 0x5d, 0xd2, 0x22, 0x16, 0x07, 0x2e, 0xd3,
0x78, 0xab, 0x4b, 0x9a, 0x56, 0x07, 0xcd, 0x43, 0xae, 0x67, 0xf6, 0x4d, 0x4f, 0xa0, 0xf2, 0x46, 0xf1, 0x56, 0x97, 0x34, 0xad, 0x0e, 0x9a, 0x87, 0x5c, 0xcf, 0xec, 0x9b, 0x9e, 0x40, 0xe5, 0x8d,
0x48, 0x9d, 0xe9, 0x88, 0x3a, 0x1b, 0x00, 0xae, 0xed, 0x78, 0x2d, 0xdb, 0xe9, 0x10, 0xa7, 0x9e, 0x90, 0x3a, 0xd3, 0x11, 0x75, 0x36, 0x00, 0x5c, 0xdb, 0xf1, 0x5a, 0xb6, 0xd3, 0x21, 0x4e, 0x3d,
0x5b, 0xd2, 0x96, 0xab, 0x6b, 0xb7, 0x56, 0xd4, 0x85, 0x58, 0x51, 0x15, 0x5a, 0x39, 0xb0, 0x1d, 0xb7, 0xa4, 0x2d, 0x57, 0xd7, 0x6e, 0xad, 0xa8, 0x0b, 0xb1, 0xa2, 0x2a, 0xb4, 0x72, 0x60, 0x3b,
0x6f, 0x9f, 0xf2, 0xea, 0x45, 0x57, 0x7e, 0xa2, 0xf7, 0xa0, 0xc4, 0x84, 0x78, 0x86, 0xd3, 0x25, 0xde, 0x3e, 0xe5, 0xd5, 0x8b, 0xae, 0xfc, 0x44, 0xef, 0x41, 0x89, 0x09, 0xf1, 0x0c, 0xa7, 0x4b,
0x5e, 0x3d, 0xcf, 0xa4, 0xdc, 0x3e, 0x47, 0xca, 0x21, 0x63, 0xd6, 0x19, 0x3c, 0xff, 0x46, 0x18, 0xbc, 0x7a, 0x9e, 0x49, 0xb9, 0x7d, 0x8e, 0x94, 0x43, 0xc6, 0xac, 0x33, 0x78, 0xfe, 0x8d, 0x30,
0xca, 0x2e, 0x71, 0x4c, 0xa3, 0x67, 0x7e, 0x62, 0x1c, 0xf5, 0x48, 0xbd, 0xb0, 0xa4, 0x2d, 0xcf, 0x94, 0x5d, 0xe2, 0x98, 0x46, 0xcf, 0xfc, 0xc4, 0x38, 0xea, 0x91, 0x7a, 0x61, 0x49, 0x5b, 0x9e,
0xe8, 0x21, 0x1a, 0x9d, 0xff, 0x09, 0x39, 0x73, 0x5b, 0xb6, 0xd5, 0x3b, 0xab, 0xcf, 0x30, 0x86, 0xd1, 0x43, 0x34, 0x3a, 0xff, 0x13, 0x72, 0xe6, 0xb6, 0x6c, 0xab, 0x77, 0x56, 0x9f, 0x61, 0x0c,
0x19, 0x4a, 0xd8, 0xb7, 0x7a, 0x67, 0x6c, 0xd1, 0xec, 0xa1, 0xe5, 0xf1, 0xde, 0x22, 0xeb, 0x2d, 0x33, 0x94, 0xb0, 0x6f, 0xf5, 0xce, 0xd8, 0xa2, 0xd9, 0x43, 0xcb, 0xe3, 0xbd, 0x45, 0xd6, 0x5b,
0x32, 0x0a, 0xeb, 0x5e, 0x86, 0x5a, 0xdf, 0xb4, 0x5a, 0x7d, 0xbb, 0xd3, 0xf2, 0x0d, 0x02, 0xcc, 0x64, 0x14, 0xd6, 0xbd, 0x0c, 0xb5, 0xbe, 0x69, 0xb5, 0xfa, 0x76, 0xa7, 0xe5, 0x1b, 0x04, 0x98,
0x20, 0xd5, 0xbe, 0x69, 0x3d, 0xb1, 0x3b, 0xba, 0x34, 0x0b, 0xe5, 0x34, 0x4e, 0xc3, 0x9c, 0x25, 0x41, 0xaa, 0x7d, 0xd3, 0x7a, 0x62, 0x77, 0x74, 0x69, 0x16, 0xca, 0x69, 0x9c, 0x86, 0x39, 0x4b,
0xc1, 0x69, 0x9c, 0xaa, 0x9c, 0x2b, 0x30, 0x47, 0x65, 0xb6, 0x1d, 0x62, 0x78, 0x24, 0x60, 0x2e, 0x82, 0xd3, 0x38, 0x55, 0x39, 0x57, 0x60, 0x8e, 0xca, 0x6c, 0x3b, 0xc4, 0xf0, 0x48, 0xc0, 0x5c,
0x33, 0xe6, 0x0b, 0x7d, 0xd3, 0xda, 0x60, 0x3d, 0x21, 0x7e, 0xe3, 0x74, 0x8c, 0xbf, 0x22, 0xf8, 0x66, 0xcc, 0x17, 0xfa, 0xa6, 0xb5, 0xc1, 0x7a, 0x42, 0xfc, 0xc6, 0xe9, 0x18, 0x7f, 0x45, 0xf0,
0x8d, 0xd3, 0x30, 0x3f, 0x5e, 0x81, 0xa2, 0x6f, 0x73, 0x34, 0x03, 0xd3, 0x7b, 0xfb, 0x7b, 0xcd, 0x1b, 0xa7, 0x61, 0x7e, 0xbc, 0x02, 0x45, 0xdf, 0xe6, 0x68, 0x06, 0xa6, 0xf7, 0xf6, 0xf7, 0x9a,
0xda, 0x14, 0x02, 0xc8, 0xaf, 0x1f, 0x6c, 0x34, 0xf7, 0x36, 0x6b, 0x1a, 0x2a, 0x41, 0x61, 0xb3, 0xb5, 0x29, 0x04, 0x90, 0x5f, 0x3f, 0xd8, 0x68, 0xee, 0x6d, 0xd6, 0x34, 0x54, 0x82, 0xc2, 0x66,
0xc9, 0x1b, 0x19, 0xfc, 0x08, 0x20, 0xb0, 0x2e, 0x2a, 0x40, 0x76, 0xa7, 0xf9, 0xff, 0xb5, 0x29, 0x93, 0x37, 0x32, 0xf8, 0x11, 0x40, 0x60, 0x5d, 0x54, 0x80, 0xec, 0x4e, 0xf3, 0xff, 0x6b, 0x53,
0xca, 0xf3, 0xbc, 0xa9, 0x1f, 0x6c, 0xef, 0xef, 0xd5, 0x34, 0x3a, 0x78, 0x43, 0x6f, 0xae, 0x1f, 0x94, 0xe7, 0x79, 0x53, 0x3f, 0xd8, 0xde, 0xdf, 0xab, 0x69, 0x74, 0xf0, 0x86, 0xde, 0x5c, 0x3f,
0x36, 0x6b, 0x19, 0xca, 0xf1, 0x64, 0x7f, 0xb3, 0x96, 0x45, 0x45, 0xc8, 0x3d, 0x5f, 0xdf, 0x7d, 0x6c, 0xd6, 0x32, 0x94, 0xe3, 0xc9, 0xfe, 0x66, 0x2d, 0x8b, 0x8a, 0x90, 0x7b, 0xbe, 0xbe, 0xfb,
0xd6, 0xac, 0x4d, 0xe3, 0x2f, 0x34, 0xa8, 0x88, 0xf5, 0xe2, 0x3e, 0x81, 0xde, 0x86, 0xfc, 0x31, 0xac, 0x59, 0x9b, 0xc6, 0x5f, 0x68, 0x50, 0x11, 0xeb, 0xc5, 0x7d, 0x02, 0xbd, 0x0d, 0xf9, 0x63,
0xf3, 0x0b, 0xb6, 0x15, 0x4b, 0x6b, 0x57, 0x23, 0x8b, 0x1b, 0xf2, 0x1d, 0x5d, 0xf0, 0x22, 0x0c, 0xe6, 0x17, 0x6c, 0x2b, 0x96, 0xd6, 0xae, 0x46, 0x16, 0x37, 0xe4, 0x3b, 0xba, 0xe0, 0x45, 0x18,
0xd9, 0x93, 0x91, 0x5b, 0xcf, 0x2c, 0x65, 0x97, 0x4b, 0x6b, 0xb5, 0x15, 0xee, 0xb0, 0x2b, 0x3b, 0xb2, 0x27, 0x23, 0xb7, 0x9e, 0x59, 0xca, 0x2e, 0x97, 0xd6, 0x6a, 0x2b, 0xdc, 0x61, 0x57, 0x76,
0xe4, 0xec, 0xb9, 0xd1, 0x1b, 0x12, 0x9d, 0x76, 0x22, 0x04, 0xd3, 0x7d, 0xdb, 0x21, 0x6c, 0xc7, 0xc8, 0xd9, 0x73, 0xa3, 0x37, 0x24, 0x3a, 0xed, 0x44, 0x08, 0xa6, 0xfb, 0xb6, 0x43, 0xd8, 0x8e,
0xce, 0xe8, 0xec, 0x9b, 0x6e, 0x63, 0xb6, 0x68, 0x62, 0xb7, 0xf2, 0x06, 0xfe, 0x9e, 0x06, 0xf0, 0x9d, 0xd1, 0xd9, 0x37, 0xdd, 0xc6, 0x6c, 0xd1, 0xc4, 0x6e, 0xe5, 0x0d, 0xfc, 0xa5, 0x06, 0xf0,
0x74, 0xe8, 0x25, 0xbb, 0xc6, 0x3c, 0xe4, 0x46, 0x54, 0xb0, 0x70, 0x0b, 0xde, 0x60, 0x3e, 0x41, 0x74, 0xe8, 0x25, 0xbb, 0xc6, 0x3c, 0xe4, 0x46, 0x54, 0xb0, 0x70, 0x0b, 0xde, 0x60, 0x3e, 0x41,
0x0c, 0x97, 0xf8, 0x3e, 0x41, 0x1b, 0xe8, 0x32, 0x14, 0x06, 0x0e, 0x19, 0xb5, 0x4e, 0x46, 0x0c, 0x0c, 0x97, 0xf8, 0x3e, 0x41, 0x1b, 0xe8, 0x32, 0x14, 0x06, 0x0e, 0x19, 0xb5, 0x4e, 0x46, 0x0c,
0x64, 0x46, 0xcf, 0xd3, 0xe6, 0xce, 0x08, 0xdd, 0x80, 0xb2, 0xd9, 0xb5, 0x6c, 0x87, 0xb4, 0xb8, 0x64, 0x46, 0xcf, 0xd3, 0xe6, 0xce, 0x08, 0xdd, 0x80, 0xb2, 0xd9, 0xb5, 0x6c, 0x87, 0xb4, 0xb8,
0xac, 0x1c, 0xeb, 0x2d, 0x71, 0x1a, 0xd3, 0x1b, 0x5b, 0x50, 0x62, 0x7a, 0xa4, 0xb2, 0xcd, 0xbd, 0xac, 0x1c, 0xeb, 0x2d, 0x71, 0x1a, 0xd3, 0x5b, 0x61, 0xe1, 0x82, 0xf3, 0x2a, 0xcb, 0x2e, 0x25,
0x40, 0x81, 0x0c, 0x1b, 0x36, 0x6e, 0x1f, 0xa1, 0x12, 0xfe, 0x08, 0xd0, 0x26, 0xe9, 0x11, 0x8f, 0x61, 0x0b, 0x4a, 0x4c, 0xd5, 0x54, 0xe6, 0xbb, 0x17, 0xe8, 0x98, 0x61, 0xc3, 0xc6, 0x4d, 0x28,
0xa4, 0x09, 0x0d, 0xca, 0x84, 0xb3, 0xea, 0x84, 0xf1, 0x8f, 0x34, 0x98, 0x0b, 0x89, 0x4f, 0x35, 0xb4, 0xc6, 0x1f, 0x01, 0xda, 0x24, 0x3d, 0xe2, 0x91, 0x34, 0xd1, 0x43, 0xb1, 0x49, 0x56, 0xb5,
0xad, 0x3a, 0x14, 0x3a, 0x4c, 0x18, 0xd7, 0x20, 0xab, 0xcb, 0x26, 0x7a, 0x00, 0x33, 0x42, 0x01, 0x09, 0xfe, 0xb1, 0x06, 0x73, 0x21, 0xf1, 0xa9, 0xa6, 0x55, 0x87, 0x42, 0x87, 0x09, 0xe3, 0x1a,
0xb7, 0x9e, 0x4d, 0xd8, 0x11, 0x05, 0xae, 0x93, 0x8b, 0xff, 0xa6, 0x41, 0x51, 0x4c, 0x74, 0x7f, 0x64, 0x75, 0xd9, 0x44, 0x0f, 0x60, 0x46, 0x28, 0xe0, 0xd6, 0xb3, 0x09, 0x9b, 0xa6, 0xc0, 0x75,
0x80, 0xd6, 0xa1, 0xe2, 0xf0, 0x46, 0x8b, 0xcd, 0x47, 0x68, 0xd4, 0x48, 0x8e, 0x30, 0x5b, 0x53, 0x72, 0xf1, 0xdf, 0x34, 0x28, 0x8a, 0x89, 0xee, 0x0f, 0xd0, 0x3a, 0x54, 0x1c, 0xde, 0x68, 0xb1,
0x7a, 0x59, 0x0c, 0x61, 0x64, 0xf4, 0x3f, 0x50, 0x92, 0x22, 0x06, 0x43, 0x4f, 0x98, 0xbc, 0x1e, 0xf9, 0x08, 0x8d, 0x1a, 0xc9, 0x41, 0x68, 0x6b, 0x4a, 0x2f, 0x8b, 0x21, 0x8c, 0x8c, 0xfe, 0x07,
0x16, 0x10, 0x6c, 0xae, 0xad, 0x29, 0x1d, 0x04, 0xfb, 0xd3, 0xa1, 0x87, 0x0e, 0x61, 0x5e, 0x0e, 0x4a, 0x52, 0xc4, 0x60, 0xe8, 0x09, 0x93, 0xd7, 0xc3, 0x02, 0x82, 0xfd, 0xb7, 0x35, 0xa5, 0x83,
0xe6, 0xb3, 0x11, 0x6a, 0x64, 0x99, 0x94, 0xa5, 0xb0, 0x94, 0xf1, 0xa5, 0xda, 0x9a, 0xd2, 0x91, 0x60, 0x7f, 0x3a, 0xf4, 0xd0, 0x21, 0xcc, 0xcb, 0xc1, 0x7c, 0x36, 0x42, 0x8d, 0x2c, 0x93, 0xb2,
0x18, 0xaf, 0x74, 0x3e, 0x2a, 0x42, 0x41, 0x50, 0xf1, 0xdf, 0x35, 0x00, 0x69, 0xd0, 0xfd, 0x01, 0x14, 0x96, 0x32, 0xbe, 0x54, 0x5b, 0x53, 0x3a, 0x12, 0xe3, 0x95, 0xce, 0x47, 0x45, 0x28, 0x08,
0xda, 0x84, 0xaa, 0x23, 0x5a, 0xa1, 0x09, 0x5f, 0x89, 0x9d, 0xb0, 0x58, 0x87, 0x29, 0xbd, 0x22, 0x2a, 0xfe, 0xbb, 0x06, 0x20, 0x0d, 0xba, 0x3f, 0x40, 0x9b, 0x50, 0x75, 0x44, 0x2b, 0x34, 0xe1,
0x07, 0xf1, 0x29, 0xbf, 0x0b, 0x65, 0x5f, 0x4a, 0x30, 0xe7, 0x85, 0x98, 0x39, 0xfb, 0x12, 0x4a, 0x2b, 0xb1, 0x13, 0x16, 0xeb, 0x30, 0xa5, 0x57, 0xe4, 0x20, 0x3e, 0xe5, 0x77, 0xa1, 0xec, 0x4b,
0x72, 0x00, 0x9d, 0xf5, 0x07, 0x70, 0xd1, 0x1f, 0x1f, 0x33, 0xed, 0x1b, 0x13, 0xa6, 0xed, 0x0b, 0x09, 0xe6, 0xbc, 0x10, 0x33, 0x67, 0x5f, 0x42, 0x49, 0x0e, 0xa0, 0xb3, 0xfe, 0x00, 0x2e, 0xfa,
0x9c, 0x93, 0x12, 0xd4, 0x89, 0x03, 0x3d, 0x8f, 0x38, 0x19, 0xff, 0x2a, 0x0b, 0x85, 0x0d, 0xbb, 0xe3, 0x63, 0xa6, 0x7d, 0x63, 0xc2, 0xb4, 0x7d, 0x81, 0x73, 0x52, 0x82, 0x3a, 0x71, 0xa0, 0x47,
0x3f, 0x30, 0x1c, 0xba, 0x46, 0x79, 0x87, 0xb8, 0xc3, 0x9e, 0xc7, 0xa6, 0x5b, 0x5d, 0xbb, 0x19, 0x16, 0x27, 0xe3, 0x2f, 0xb3, 0x50, 0xd8, 0xb0, 0xfb, 0x03, 0xc3, 0xa1, 0x6b, 0x94, 0x77, 0x88,
0x46, 0x10, 0x6c, 0xf2, 0xaf, 0xce, 0x58, 0x75, 0x31, 0x84, 0x0e, 0x16, 0xc7, 0x4f, 0xe6, 0x15, 0x3b, 0xec, 0x79, 0x6c, 0xba, 0xd5, 0xb5, 0x9b, 0x61, 0x04, 0xc1, 0x26, 0xff, 0xea, 0x8c, 0x55,
0x06, 0x8b, 0xc3, 0x47, 0x0c, 0x91, 0xbe, 0x94, 0x0d, 0x7c, 0xa9, 0x01, 0x85, 0x11, 0x71, 0x82, 0x17, 0x43, 0xe8, 0x60, 0x71, 0x42, 0x65, 0x5e, 0x61, 0xb0, 0x38, 0x9f, 0xc4, 0x10, 0xe9, 0x4b,
0x23, 0x73, 0x6b, 0x4a, 0x97, 0x04, 0x74, 0x0f, 0x66, 0xa3, 0xe1, 0x3b, 0x27, 0x78, 0xaa, 0xed, 0xd9, 0xc0, 0x97, 0x1a, 0x50, 0x18, 0x11, 0x27, 0x38, 0x55, 0xb7, 0xa6, 0x74, 0x49, 0x40, 0xf7,
0x70, 0xb4, 0xbf, 0x09, 0xe5, 0xd0, 0x19, 0x92, 0x17, 0x7c, 0xa5, 0xbe, 0x72, 0x84, 0x5c, 0x92, 0x60, 0x36, 0x1a, 0xe1, 0x73, 0x82, 0xa7, 0xda, 0x0e, 0x1f, 0x08, 0x37, 0xa1, 0x1c, 0x3a, 0x66,
0x71, 0x8b, 0x9e, 0x77, 0xe5, 0xad, 0x29, 0x11, 0xb9, 0xf0, 0xff, 0x42, 0x25, 0x34, 0x57, 0x1a, 0xf2, 0x82, 0xaf, 0xd4, 0x57, 0x4e, 0x99, 0x4b, 0x32, 0xb4, 0xd1, 0x23, 0xb1, 0xbc, 0x35, 0x25,
0xa2, 0x9b, 0xef, 0x3f, 0x5b, 0xdf, 0xe5, 0xf1, 0xfc, 0x31, 0x0b, 0xe1, 0x7a, 0x4d, 0xa3, 0xc7, 0x82, 0x1b, 0xfe, 0x5f, 0xa8, 0x84, 0xe6, 0x4a, 0xa3, 0x78, 0xf3, 0xfd, 0x67, 0xeb, 0xbb, 0x3c,
0xc2, 0x6e, 0xf3, 0xe0, 0xa0, 0x96, 0x41, 0x15, 0x28, 0xee, 0xed, 0x1f, 0xb6, 0x38, 0x57, 0x16, 0xe4, 0x3f, 0x66, 0x51, 0x5e, 0xaf, 0x69, 0xf4, 0xe4, 0xd8, 0x6d, 0x1e, 0x1c, 0xd4, 0x32, 0xa8,
0xbf, 0xe3, 0x4b, 0x10, 0xe7, 0x81, 0x72, 0x0c, 0x4c, 0x29, 0xc7, 0x80, 0x26, 0x8f, 0x81, 0x4c, 0x02, 0xc5, 0xbd, 0xfd, 0xc3, 0x16, 0xe7, 0xca, 0xe2, 0x77, 0x7c, 0x09, 0xe2, 0xc8, 0x50, 0x4e,
0x70, 0x0c, 0x64, 0x1f, 0x55, 0xa1, 0xcc, 0xed, 0xd3, 0x1a, 0x5a, 0xf4, 0x28, 0xfa, 0x85, 0x06, 0x8a, 0x29, 0xe5, 0xa4, 0xd0, 0xe4, 0x49, 0x91, 0x09, 0x4e, 0x8a, 0xec, 0xa3, 0x2a, 0x94, 0xb9,
0x70, 0x78, 0x6a, 0xc9, 0x00, 0xb4, 0x0a, 0x85, 0x36, 0x17, 0x5e, 0xd7, 0x98, 0x3f, 0x5f, 0x8c, 0x7d, 0x5a, 0x43, 0x8b, 0x9e, 0x56, 0xbf, 0xd4, 0x00, 0x0e, 0x4f, 0x2d, 0x19, 0x80, 0x56, 0xa1,
0x35, 0xb9, 0x2e, 0xb9, 0xd0, 0x9b, 0x50, 0x70, 0x87, 0xed, 0x36, 0x71, 0xe5, 0x91, 0x70, 0x39, 0xd0, 0xe6, 0xc2, 0xeb, 0x1a, 0xf3, 0xe7, 0x8b, 0xb1, 0x26, 0xd7, 0x25, 0x17, 0x7a, 0x13, 0x0a,
0x1a, 0x52, 0x84, 0xc3, 0xeb, 0x92, 0x8f, 0x0e, 0x79, 0x61, 0x98, 0xbd, 0x21, 0x3b, 0x20, 0x26, 0xee, 0xb0, 0xdd, 0x26, 0xae, 0x3c, 0x35, 0x2e, 0x47, 0x43, 0x8a, 0x70, 0x78, 0x5d, 0xf2, 0xd1,
0x0f, 0x11, 0x7c, 0xf8, 0xa7, 0x1a, 0x94, 0x98, 0x96, 0xa9, 0xe2, 0xd8, 0x55, 0x28, 0x32, 0x1d, 0x21, 0x2f, 0x0c, 0xb3, 0x37, 0x64, 0x67, 0xc8, 0xe4, 0x21, 0x82, 0x0f, 0xff, 0x4c, 0x83, 0x12,
0x48, 0x47, 0x44, 0xb2, 0x19, 0x3d, 0x20, 0xa0, 0xff, 0x86, 0xa2, 0xdc, 0xc1, 0x32, 0x98, 0xd5, 0xd3, 0x32, 0x55, 0x1c, 0xbb, 0x0a, 0x45, 0xa6, 0x03, 0xe9, 0x88, 0x48, 0x36, 0xa3, 0x07, 0x04,
0xe3, 0xc5, 0xee, 0x0f, 0xf4, 0x80, 0x15, 0xef, 0xc0, 0x05, 0x66, 0x95, 0x36, 0x4d, 0x3e, 0xa5, 0xf4, 0xdf, 0x50, 0x94, 0x3b, 0x58, 0x06, 0xb3, 0x7a, 0xbc, 0xd8, 0xfd, 0x81, 0x1e, 0xb0, 0xe2,
0x1d, 0xd5, 0xf4, 0x4c, 0x8b, 0xa4, 0x67, 0x0d, 0x98, 0x19, 0x1c, 0x9f, 0xb9, 0x66, 0xdb, 0xe8, 0x1d, 0xb8, 0xc0, 0xac, 0xd2, 0xa6, 0xf9, 0xa9, 0xb4, 0xa3, 0x9a, 0xc1, 0x69, 0x91, 0x0c, 0xae,
0x09, 0x2d, 0xfc, 0x36, 0xfe, 0x3f, 0x40, 0xaa, 0xb0, 0x34, 0xd3, 0xc5, 0x15, 0x28, 0x6d, 0x19, 0x01, 0x33, 0x83, 0xe3, 0x33, 0xd7, 0x6c, 0x1b, 0x3d, 0xa1, 0x85, 0xdf, 0xc6, 0xff, 0x07, 0x48,
0xee, 0xb1, 0x50, 0x09, 0x7f, 0x08, 0x65, 0xde, 0x4c, 0x65, 0x43, 0x04, 0xd3, 0xc7, 0x86, 0x7b, 0x15, 0x96, 0x66, 0xba, 0xb8, 0x02, 0xa5, 0x2d, 0xc3, 0x3d, 0x16, 0x2a, 0xe1, 0x0f, 0xa1, 0xcc,
0xcc, 0x14, 0xaf, 0xe8, 0xec, 0x1b, 0x5f, 0x80, 0xd9, 0x03, 0xcb, 0x18, 0xb8, 0xc7, 0xb6, 0x8c, 0x9b, 0xa9, 0x6c, 0x88, 0x60, 0xfa, 0xd8, 0x70, 0x8f, 0x99, 0xe2, 0x15, 0x9d, 0x7d, 0xe3, 0x0b,
0xb5, 0x34, 0xf9, 0xae, 0x05, 0xb4, 0x54, 0x88, 0x77, 0x61, 0xd6, 0x21, 0x7d, 0xc3, 0xb4, 0x4c, 0x30, 0x7b, 0x60, 0x19, 0x03, 0xf7, 0xd8, 0x96, 0xb1, 0x96, 0xe6, 0xe7, 0xb5, 0x80, 0x96, 0x0a,
0xab, 0xdb, 0x3a, 0x3a, 0xf3, 0x88, 0x2b, 0x72, 0xf3, 0xaa, 0x4f, 0x7e, 0x44, 0xa9, 0x54, 0xb5, 0xf1, 0x2e, 0xcc, 0x3a, 0xa4, 0x6f, 0x98, 0x96, 0x69, 0x75, 0x5b, 0x47, 0x67, 0x1e, 0x71, 0x45,
0xa3, 0x9e, 0x7d, 0x24, 0x3c, 0x9e, 0x7d, 0xe3, 0x5f, 0x6b, 0x50, 0xfe, 0xc0, 0xf0, 0xda, 0xd2, 0xfa, 0x5e, 0xf5, 0xc9, 0x8f, 0x28, 0x95, 0xaa, 0x76, 0xd4, 0xb3, 0x8f, 0x84, 0xc7, 0xb3, 0x6f,
0x0a, 0x68, 0x1b, 0xaa, 0xbe, 0x9f, 0x33, 0x8a, 0xd0, 0x25, 0x12, 0xf0, 0xd9, 0x18, 0x99, 0xb5, 0xfc, 0x6b, 0x0d, 0xca, 0x1f, 0x18, 0x5e, 0x5b, 0x5a, 0x01, 0x6d, 0x43, 0xd5, 0xf7, 0x73, 0x46,
0xc9, 0x80, 0x5f, 0x69, 0xab, 0x04, 0x26, 0xca, 0xb0, 0xda, 0xa4, 0xe7, 0x8b, 0xca, 0x24, 0x8b, 0x11, 0xba, 0x44, 0x02, 0x3e, 0x1b, 0x23, 0x13, 0x3b, 0x19, 0xf0, 0x2b, 0x6d, 0x95, 0xc0, 0x44,
0x62, 0x8c, 0xaa, 0x28, 0x95, 0xf0, 0x68, 0x36, 0x38, 0x0c, 0xb9, 0x5b, 0xfe, 0x2c, 0x03, 0x68, 0x19, 0x56, 0x9b, 0xf4, 0x7c, 0x51, 0x99, 0x64, 0x51, 0x8c, 0x51, 0x15, 0xa5, 0x12, 0x1e, 0xcd,
0x5c, 0x87, 0xaf, 0x9a, 0x1f, 0xdc, 0x86, 0xaa, 0xeb, 0x19, 0x8e, 0xd7, 0x8a, 0xdc, 0x5c, 0x2a, 0x06, 0x87, 0x21, 0x77, 0xcb, 0x9f, 0x67, 0x00, 0x8d, 0xeb, 0xf0, 0x75, 0xf3, 0x83, 0xdb, 0x50,
0x8c, 0xea, 0xc7, 0xaa, 0xbb, 0x30, 0x3b, 0x70, 0xec, 0xae, 0x43, 0x5c, 0xb7, 0x65, 0xd9, 0x9e, 0x75, 0x3d, 0xc3, 0xf1, 0x5a, 0x91, 0xcb, 0x4d, 0x85, 0x51, 0xfd, 0x58, 0x75, 0x17, 0x66, 0x07,
0xf9, 0xe2, 0x4c, 0xe4, 0x4f, 0x55, 0x49, 0xde, 0x63, 0x54, 0xd4, 0x84, 0xc2, 0x0b, 0xb3, 0xe7, 0x8e, 0xdd, 0x75, 0x88, 0xeb, 0xb6, 0x2c, 0xdb, 0x33, 0x5f, 0x9c, 0x89, 0x14, 0xab, 0x2a, 0xc9,
0x11, 0xc7, 0xad, 0xe7, 0x96, 0xb2, 0xcb, 0xd5, 0xb5, 0x07, 0xe7, 0x59, 0x6d, 0xe5, 0x3d, 0xc6, 0x7b, 0x8c, 0x8a, 0x9a, 0x50, 0x78, 0x61, 0xf6, 0x3c, 0xe2, 0xb8, 0xf5, 0xdc, 0x52, 0x76, 0xb9,
0x7f, 0x78, 0x36, 0x20, 0xba, 0x1c, 0xab, 0xa6, 0x2d, 0xf9, 0x50, 0xda, 0x72, 0x1b, 0x20, 0xe0, 0xba, 0xf6, 0xe0, 0x3c, 0xab, 0xad, 0xbc, 0xc7, 0xf8, 0x0f, 0xcf, 0x06, 0x44, 0x97, 0x63, 0xd5,
0xa7, 0x51, 0x6b, 0x6f, 0xff, 0xe9, 0xb3, 0xc3, 0xda, 0x14, 0x2a, 0xc3, 0xcc, 0xde, 0xfe, 0x66, 0xb4, 0x25, 0x1f, 0x4a, 0x5b, 0x6e, 0x03, 0x04, 0xfc, 0x34, 0x6a, 0xed, 0xed, 0x3f, 0x7d, 0x76,
0x73, 0xb7, 0x49, 0xe3, 0x1a, 0x5e, 0x95, 0xb6, 0x51, 0x6d, 0x88, 0x16, 0x60, 0xe6, 0x25, 0xa5, 0x58, 0x9b, 0x42, 0x65, 0x98, 0xd9, 0xdb, 0xdf, 0x6c, 0xee, 0x36, 0x69, 0x5c, 0xc3, 0xab, 0xd2,
0xca, 0xab, 0x5d, 0x56, 0x2f, 0xb0, 0xf6, 0x76, 0x07, 0xff, 0x55, 0x83, 0x8a, 0xd8, 0x05, 0xa9, 0x36, 0xaa, 0x0d, 0xd1, 0x02, 0xcc, 0xbc, 0xa4, 0x54, 0x79, 0xfb, 0xcb, 0xea, 0x05, 0xd6, 0xde,
0xb6, 0xa2, 0x0a, 0x91, 0x09, 0x41, 0xd0, 0x1c, 0x89, 0xef, 0x8e, 0x8e, 0x48, 0xc5, 0x64, 0x93, 0xee, 0xe0, 0xbf, 0x6a, 0x50, 0x11, 0xbb, 0x20, 0xd5, 0x56, 0x54, 0x21, 0x32, 0x21, 0x08, 0x9a,
0xba, 0x3b, 0x5f, 0x6c, 0xd2, 0x11, 0x66, 0xf5, 0xdb, 0xe8, 0x1e, 0xd4, 0xda, 0xdc, 0xdd, 0x23, 0x23, 0xf1, 0xdd, 0xd1, 0x11, 0xa9, 0x98, 0x6c, 0x52, 0x77, 0xe7, 0x8b, 0x4d, 0x3a, 0xc2, 0xac,
0xc7, 0x8e, 0x3e, 0x2b, 0xe8, 0xfe, 0x22, 0xdd, 0x86, 0x3c, 0x19, 0x11, 0xcb, 0x73, 0xeb, 0x25, 0x7e, 0x1b, 0xdd, 0x83, 0x5a, 0x9b, 0xbb, 0x7b, 0xe4, 0xd8, 0xd1, 0x67, 0x05, 0xdd, 0x5f, 0xa4,
0x16, 0x9b, 0x2a, 0x32, 0xd1, 0x6a, 0x52, 0xaa, 0x2e, 0x3a, 0xf1, 0x7f, 0xc1, 0x85, 0x5d, 0x9a, 0xdb, 0x90, 0x27, 0x23, 0x62, 0x79, 0x6e, 0xbd, 0xc4, 0x62, 0x53, 0x45, 0x26, 0x5a, 0x4d, 0x4a,
0x0c, 0x3f, 0x76, 0x0c, 0x4b, 0x4d, 0xab, 0x0f, 0x0f, 0x77, 0x85, 0x55, 0xe8, 0x27, 0xaa, 0x42, 0xd5, 0x45, 0x27, 0xfe, 0x2f, 0xb8, 0xc0, 0x12, 0xda, 0xc7, 0x8e, 0x61, 0xa9, 0x99, 0xf7, 0xe1,
0x66, 0x7b, 0x53, 0xcc, 0x21, 0xb3, 0xbd, 0x89, 0x3f, 0xd5, 0x00, 0xa9, 0xe3, 0x52, 0x99, 0x29, 0xe1, 0xae, 0xb0, 0x0a, 0xfd, 0x44, 0x55, 0xc8, 0x6c, 0x6f, 0x8a, 0x39, 0x64, 0xb6, 0x37, 0xf1,
0x22, 0x5c, 0xc2, 0x67, 0x03, 0xf8, 0x79, 0xc8, 0x11, 0xc7, 0xb1, 0x1d, 0x66, 0x90, 0xa2, 0xce, 0xa7, 0x1a, 0x20, 0x75, 0x5c, 0x2a, 0x33, 0x45, 0x84, 0x4b, 0xf8, 0x6c, 0x00, 0x3f, 0x0f, 0x39,
0x1b, 0xf8, 0x96, 0xd0, 0x41, 0x27, 0x23, 0xfb, 0xc4, 0xdf, 0xf3, 0x5c, 0x9a, 0xe6, 0xab, 0xba, 0xe2, 0x38, 0xb6, 0xc3, 0x0c, 0x52, 0xd4, 0x79, 0x03, 0xdf, 0x12, 0x3a, 0xe8, 0x64, 0x64, 0x9f,
0x03, 0x73, 0x21, 0xae, 0x54, 0x31, 0xf2, 0x2e, 0x5c, 0x64, 0xc2, 0x76, 0x08, 0x19, 0xac, 0xf7, 0xf8, 0x7b, 0x9e, 0x4b, 0xd3, 0x7c, 0x55, 0x77, 0x60, 0x2e, 0xc4, 0x95, 0x2a, 0x46, 0xde, 0x85,
0xcc, 0x51, 0x22, 0xea, 0x00, 0x2e, 0x45, 0x19, 0xbf, 0x5e, 0x1b, 0xe1, 0x77, 0x04, 0xe2, 0xa1, 0x8b, 0x4c, 0xd8, 0x0e, 0x21, 0x83, 0xf5, 0x9e, 0x39, 0x4a, 0x44, 0x1d, 0xc0, 0xa5, 0x28, 0xe3,
0xd9, 0x27, 0x87, 0xf6, 0x6e, 0xb2, 0x6e, 0x34, 0xf0, 0xd1, 0xdb, 0xb2, 0x38, 0x4c, 0xd8, 0x37, 0x37, 0x6b, 0x23, 0xfc, 0x8e, 0x40, 0x3c, 0x34, 0xfb, 0xe4, 0xd0, 0xde, 0x4d, 0xd6, 0x8d, 0x06,
0xfe, 0xa5, 0x06, 0x97, 0xc7, 0x86, 0x7f, 0xcd, 0xab, 0xba, 0x08, 0xd0, 0xa5, 0xdb, 0x87, 0x74, 0x3e, 0x7a, 0xa1, 0x16, 0x87, 0x09, 0xfb, 0xc6, 0xbf, 0xd2, 0xe0, 0xf2, 0xd8, 0xf0, 0x6f, 0x78,
0x68, 0x07, 0xbf, 0xe7, 0x29, 0x14, 0x5f, 0x4f, 0x1a, 0x3b, 0xca, 0x42, 0xcf, 0x63, 0xc8, 0x3f, 0x55, 0x17, 0x01, 0xba, 0x74, 0xfb, 0x90, 0x0e, 0xed, 0xe0, 0x57, 0x41, 0x85, 0xe2, 0xeb, 0x49,
0x61, 0x25, 0x16, 0x65, 0x56, 0xd3, 0x72, 0x56, 0x96, 0xd1, 0xe7, 0x17, 0xbf, 0xa2, 0xce, 0xbe, 0x63, 0x47, 0x59, 0xe8, 0x79, 0x0c, 0xf9, 0x27, 0xac, 0x0a, 0xa3, 0xcc, 0x6a, 0x5a, 0xce, 0xca,
0xd9, 0xd1, 0x49, 0x88, 0xf3, 0x4c, 0xdf, 0xe5, 0x47, 0x74, 0x51, 0xf7, 0xdb, 0x14, 0xbd, 0xdd, 0x32, 0xfa, 0xfc, 0x6e, 0x58, 0xd4, 0xd9, 0x37, 0x3b, 0x3a, 0x09, 0x71, 0x9e, 0xe9, 0xbb, 0xfc,
0x33, 0x89, 0xe5, 0xb1, 0xde, 0x69, 0xd6, 0xab, 0x50, 0xf0, 0x0a, 0xd4, 0x38, 0xd2, 0x7a, 0xa7, 0x88, 0x2e, 0xea, 0x7e, 0x9b, 0xa2, 0xb7, 0x7b, 0x26, 0xb1, 0x3c, 0xd6, 0x3b, 0xcd, 0x7a, 0x15,
0xa3, 0x1c, 0xd3, 0xbe, 0x3c, 0x2d, 0x2c, 0x0f, 0xbf, 0x84, 0x0b, 0x0a, 0x7f, 0x2a, 0xd3, 0xbd, 0x0a, 0x5e, 0x81, 0x1a, 0x47, 0x5a, 0xef, 0x74, 0x94, 0x63, 0xda, 0x97, 0xa7, 0x85, 0xe5, 0xe1,
0x06, 0x79, 0x5e, 0x47, 0x12, 0x27, 0xc4, 0x7c, 0x78, 0x14, 0x87, 0xd1, 0x05, 0x0f, 0xbe, 0x0d, 0x97, 0x70, 0x41, 0xe1, 0x4f, 0x65, 0xba, 0xd7, 0x20, 0xcf, 0x4b, 0x4d, 0xe2, 0x84, 0x98, 0x0f,
0x73, 0x82, 0x42, 0xfa, 0x76, 0xdc, 0xaa, 0x33, 0xfb, 0xe0, 0x5d, 0x98, 0x0f, 0xb3, 0xa5, 0x72, 0x8f, 0xe2, 0x30, 0xba, 0xe0, 0xc1, 0xb7, 0x61, 0x4e, 0x50, 0x48, 0xdf, 0x8e, 0x5b, 0x75, 0x66,
0x84, 0x75, 0x09, 0xfa, 0x6c, 0xd0, 0x51, 0x0e, 0x9c, 0xe8, 0xa2, 0xa8, 0x06, 0xcb, 0x44, 0x0c, 0x1f, 0xbc, 0x0b, 0xf3, 0x61, 0xb6, 0x54, 0x8e, 0xb0, 0x2e, 0x41, 0x9f, 0x0d, 0x3a, 0xca, 0x81,
0xe6, 0x2b, 0x24, 0x45, 0xa4, 0x52, 0x68, 0x4e, 0x9a, 0x7f, 0xd7, 0x74, 0xfd, 0xb4, 0xe2, 0x13, 0x13, 0x5d, 0x14, 0xd5, 0x60, 0x99, 0x88, 0xc1, 0x7c, 0x85, 0xa4, 0x88, 0x54, 0x0a, 0xcd, 0x49,
0x40, 0x2a, 0x31, 0xd5, 0xa2, 0xac, 0x40, 0x81, 0x1b, 0x5c, 0x66, 0xae, 0xf1, 0xab, 0x22, 0x99, 0xf3, 0xef, 0x9a, 0xae, 0x9f, 0x56, 0x7c, 0x02, 0x48, 0x25, 0xa6, 0x5a, 0x94, 0x15, 0x28, 0x70,
0xa8, 0x42, 0x9b, 0xe4, 0x85, 0x63, 0x74, 0xfb, 0xc4, 0x8f, 0xac, 0x34, 0x5f, 0x53, 0x89, 0xa9, 0x83, 0xcb, 0xcc, 0x35, 0x7e, 0x55, 0x24, 0x13, 0x55, 0x68, 0x93, 0xbc, 0x70, 0x8c, 0x6e, 0x9f,
0x66, 0xfc, 0x7b, 0x0d, 0xca, 0xeb, 0x3d, 0xc3, 0xe9, 0x4b, 0xe3, 0xbf, 0x0b, 0x79, 0x9e, 0x08, 0xf8, 0x91, 0x95, 0xe6, 0x6b, 0x2a, 0x31, 0xd5, 0x8c, 0x7f, 0xaf, 0x41, 0x79, 0xbd, 0x67, 0x38,
0x8a, 0xbb, 0xd3, 0x9d, 0xb0, 0x18, 0x95, 0x97, 0x37, 0xd6, 0x79, 0xda, 0x28, 0x46, 0xd1, 0xc5, 0x7d, 0x69, 0xfc, 0x77, 0x21, 0xcf, 0x13, 0x41, 0x71, 0x77, 0xba, 0x13, 0x16, 0xa3, 0xf2, 0xf2,
0x12, 0xe5, 0xcb, 0xcd, 0x48, 0x39, 0x73, 0x13, 0xbd, 0x0e, 0x39, 0x83, 0x0e, 0x61, 0xfe, 0x5b, 0xc6, 0x3a, 0x4f, 0x1b, 0xc5, 0x28, 0xba, 0x58, 0xa2, 0xc2, 0xb9, 0x19, 0xa9, 0x78, 0x6e, 0xa2,
0x8d, 0xa6, 0xe0, 0x4c, 0x1a, 0x3b, 0xb4, 0x39, 0x17, 0x7e, 0x1b, 0x4a, 0x0a, 0x02, 0xbd, 0x59, 0xd7, 0x21, 0x67, 0xd0, 0x21, 0xcc, 0x7f, 0xab, 0xd1, 0x14, 0x9c, 0x49, 0x63, 0x87, 0x36, 0xe7,
0x3c, 0x6e, 0x8a, 0x83, 0x79, 0x7d, 0xe3, 0x70, 0xfb, 0x39, 0xbf, 0x70, 0x54, 0x01, 0x36, 0x9b, 0xc2, 0x6f, 0x43, 0x49, 0x41, 0xa0, 0x37, 0x8b, 0xc7, 0x4d, 0x71, 0x30, 0xaf, 0x6f, 0x1c, 0x6e,
0x7e, 0x3b, 0x83, 0x3f, 0x14, 0xa3, 0x84, 0x87, 0xab, 0xfa, 0x68, 0x49, 0xfa, 0x64, 0x5e, 0x49, 0x3f, 0xe7, 0x17, 0x8e, 0x2a, 0xc0, 0x66, 0xd3, 0x6f, 0x67, 0xf0, 0x87, 0x62, 0x94, 0xf0, 0x70,
0x9f, 0x53, 0xa8, 0x88, 0xe9, 0xa7, 0xda, 0x03, 0x6f, 0x42, 0x9e, 0xc9, 0x93, 0x5b, 0x60, 0x21, 0x55, 0x1f, 0x2d, 0x49, 0x9f, 0xcc, 0x2b, 0xe9, 0x73, 0x0a, 0x15, 0x31, 0xfd, 0x54, 0x7b, 0xe0,
0x06, 0x56, 0x7a, 0x27, 0x67, 0xc4, 0xb3, 0x50, 0x39, 0xf0, 0x0c, 0x6f, 0xe8, 0xca, 0x2d, 0xf0, 0x4d, 0xc8, 0x33, 0x79, 0x72, 0x0b, 0x2c, 0xc4, 0xc0, 0x4a, 0xef, 0xe4, 0x8c, 0x78, 0x16, 0x2a,
0x3b, 0x0d, 0xaa, 0x92, 0x92, 0xb6, 0xcc, 0x22, 0xaf, 0xa7, 0x3c, 0xe6, 0xf9, 0x97, 0xd3, 0x4b, 0x07, 0x9e, 0xe1, 0x0d, 0x5d, 0xb9, 0x05, 0x7e, 0xa7, 0x41, 0x55, 0x52, 0xd2, 0x96, 0x59, 0xe4,
0x90, 0xef, 0x1c, 0x1d, 0x98, 0x9f, 0xc8, 0x7a, 0x97, 0x68, 0x51, 0x7a, 0x8f, 0xe3, 0xf0, 0xa2, 0xf5, 0x94, 0xc7, 0x3c, 0xff, 0x72, 0x7a, 0x09, 0xf2, 0x9d, 0xa3, 0x03, 0xf3, 0x13, 0x59, 0x12,
0xb3, 0x68, 0xd1, 0x8b, 0x8e, 0x63, 0xbc, 0xf0, 0xb6, 0xad, 0x0e, 0x39, 0x65, 0xf9, 0xc4, 0xb4, 0x13, 0x2d, 0x4a, 0xef, 0x71, 0x1c, 0x5e, 0x97, 0x16, 0x2d, 0x7a, 0xd1, 0x71, 0x8c, 0x17, 0xde,
0x1e, 0x10, 0xd8, 0xdd, 0x44, 0x14, 0xa7, 0x59, 0xfe, 0xa5, 0x16, 0xab, 0xe7, 0xe0, 0xc2, 0xfa, 0xb6, 0xd5, 0x21, 0xa7, 0x2c, 0x9f, 0x98, 0xd6, 0x03, 0x02, 0xbb, 0x9b, 0x88, 0xfa, 0x35, 0xcb,
0xd0, 0x3b, 0x6e, 0x5a, 0xc6, 0x51, 0x4f, 0x06, 0x01, 0x3c, 0x0f, 0x88, 0x12, 0x37, 0x4d, 0x57, 0xbf, 0xd4, 0x7a, 0xf6, 0x1c, 0x5c, 0x58, 0x1f, 0x7a, 0xc7, 0x4d, 0xcb, 0x38, 0xea, 0xc9, 0x20,
0xa5, 0x36, 0x61, 0x8e, 0x52, 0x89, 0xe5, 0x99, 0x6d, 0x25, 0x62, 0xc8, 0xb0, 0xad, 0x45, 0xc2, 0x80, 0xe7, 0x01, 0x51, 0xe2, 0xa6, 0xe9, 0xaa, 0xd4, 0x26, 0xcc, 0x51, 0x2a, 0xb1, 0x3c, 0xb3,
0xb6, 0xe1, 0xba, 0x2f, 0x6d, 0xa7, 0x23, 0xa6, 0xe6, 0xb7, 0xf1, 0x26, 0x17, 0xfe, 0xcc, 0x0d, 0xad, 0x44, 0x0c, 0x19, 0xb6, 0xb5, 0x48, 0xd8, 0x36, 0x5c, 0xf7, 0xa5, 0xed, 0x74, 0xc4, 0xd4,
0x05, 0xe6, 0xaf, 0x2a, 0x65, 0x39, 0x90, 0xf2, 0x98, 0x78, 0x13, 0xa4, 0xe0, 0x07, 0x70, 0x51, 0xfc, 0x36, 0xde, 0xe4, 0xc2, 0x9f, 0xb9, 0xa1, 0xc0, 0xfc, 0x75, 0xa5, 0x2c, 0x07, 0x52, 0x1e,
0x72, 0x8a, 0xfa, 0xc5, 0x04, 0xe6, 0x7d, 0xb8, 0x26, 0x99, 0x37, 0x8e, 0x69, 0x56, 0xfd, 0x54, 0x13, 0x6f, 0x82, 0x14, 0xfc, 0x00, 0x2e, 0x4a, 0x4e, 0x51, 0xbf, 0x98, 0xc0, 0xbc, 0x0f, 0xd7,
0x00, 0xfe, 0xbb, 0x7a, 0x3e, 0x82, 0xba, 0xaf, 0x27, 0xcb, 0xb4, 0xec, 0x9e, 0xaa, 0xc0, 0xd0, 0x24, 0xf3, 0xc6, 0x31, 0xcd, 0xaa, 0x9f, 0x0a, 0xc0, 0x7f, 0x57, 0xcf, 0x47, 0x50, 0xf7, 0xf5,
0x15, 0x7b, 0xa6, 0xa8, 0xb3, 0x6f, 0x4a, 0x73, 0xec, 0x9e, 0x7f, 0x08, 0xd2, 0x6f, 0xbc, 0x01, 0x64, 0x99, 0x96, 0xdd, 0x53, 0x15, 0x18, 0xba, 0x62, 0xcf, 0x14, 0x75, 0xf6, 0x4d, 0x69, 0x8e,
0x0b, 0x52, 0x86, 0xc8, 0x81, 0xc2, 0x42, 0xc6, 0x14, 0x8a, 0x13, 0x22, 0x0c, 0x46, 0x87, 0x4e, 0xdd, 0xf3, 0x0f, 0x41, 0xfa, 0x8d, 0x37, 0x60, 0x41, 0xca, 0x10, 0x39, 0x50, 0x58, 0xc8, 0x98,
0x36, 0xbb, 0xca, 0x19, 0x36, 0x2d, 0x93, 0xa9, 0x29, 0x32, 0x2f, 0xf2, 0x1d, 0x41, 0x15, 0x53, 0x42, 0x71, 0x42, 0x84, 0xc1, 0xe8, 0xd0, 0xc9, 0x66, 0x57, 0x39, 0xc3, 0xa6, 0x65, 0x32, 0x35,
0x83, 0xb6, 0x20, 0x53, 0x01, 0x2a, 0x59, 0x2c, 0x04, 0x25, 0x8f, 0x2d, 0xc4, 0x98, 0xe8, 0x8f, 0x45, 0xe6, 0x45, 0xbe, 0x23, 0xa8, 0x62, 0x6a, 0xd0, 0x16, 0x64, 0x2a, 0x40, 0x25, 0x8b, 0x85,
0x60, 0xd1, 0x57, 0x82, 0xda, 0xed, 0x29, 0x71, 0xfa, 0xa6, 0xeb, 0x2a, 0x37, 0xee, 0xb8, 0x89, 0xa0, 0xe4, 0xb1, 0x85, 0x18, 0x13, 0xfd, 0x11, 0x2c, 0xfa, 0x4a, 0x50, 0xbb, 0x3d, 0x25, 0x4e,
0xdf, 0x81, 0xe9, 0x01, 0x11, 0x31, 0xa5, 0xb4, 0x86, 0x56, 0xf8, 0x13, 0xd2, 0x8a, 0x32, 0x98, 0xdf, 0x74, 0x5d, 0xe5, 0xc6, 0x1d, 0x37, 0xf1, 0x3b, 0x30, 0x3d, 0x20, 0x22, 0xa6, 0x94, 0xd6,
0xf5, 0xe3, 0x0e, 0x5c, 0x97, 0xd2, 0xb9, 0x45, 0x63, 0xc5, 0x47, 0x95, 0x92, 0xb7, 0x31, 0x6e, 0xd0, 0x0a, 0x7f, 0x65, 0x5a, 0x51, 0x06, 0xb3, 0x7e, 0xdc, 0x81, 0xeb, 0x52, 0x3a, 0xb7, 0x68,
0xd6, 0xf1, 0xdb, 0x58, 0x96, 0xaf, 0xbd, 0xbc, 0x8d, 0xd1, 0xb3, 0x42, 0xf5, 0xad, 0x54, 0x67, 0xac, 0xf8, 0xa8, 0x52, 0xf2, 0x36, 0xc6, 0xcd, 0x3a, 0x7e, 0x1b, 0xcb, 0xf2, 0xb5, 0x97, 0xb7,
0xc5, 0x0e, 0xb7, 0xa9, 0xef, 0x92, 0xa9, 0x84, 0x1d, 0xc1, 0x7c, 0xd8, 0x93, 0x53, 0x85, 0xb1, 0x31, 0x7a, 0x56, 0xa8, 0xbe, 0x95, 0xea, 0xac, 0xd8, 0xe1, 0x36, 0xf5, 0x5d, 0x32, 0x95, 0xb0,
0x79, 0xc8, 0x79, 0xf6, 0x09, 0x91, 0x41, 0x8c, 0x37, 0xa4, 0xc2, 0xbe, 0x9b, 0xa7, 0x52, 0xd8, 0x23, 0x98, 0x0f, 0x7b, 0x72, 0xaa, 0x30, 0x36, 0x0f, 0x39, 0xcf, 0x3e, 0x21, 0x32, 0x88, 0xf1,
0x08, 0x84, 0xb1, 0x2d, 0x99, 0x56, 0x5f, 0xba, 0x9a, 0x32, 0x9f, 0xe1, 0x0d, 0xbc, 0x07, 0x97, 0x86, 0x54, 0xd8, 0x77, 0xf3, 0x54, 0x0a, 0x1b, 0x81, 0x30, 0xb6, 0x25, 0xd3, 0xea, 0x4b, 0x57,
0xa2, 0x61, 0x22, 0x95, 0xca, 0xcf, 0xf9, 0x06, 0x8e, 0x8b, 0x24, 0xa9, 0xe4, 0xbe, 0x1f, 0x04, 0x53, 0xe6, 0x33, 0xbc, 0x81, 0xf7, 0xe0, 0x52, 0x34, 0x4c, 0xa4, 0x52, 0xf9, 0x39, 0xdf, 0xc0,
0x03, 0x25, 0xa0, 0xa4, 0x12, 0xa9, 0x43, 0x23, 0x2e, 0xbe, 0xfc, 0x27, 0xf6, 0xab, 0x1f, 0x6e, 0x71, 0x91, 0x24, 0x95, 0xdc, 0xf7, 0x83, 0x60, 0xa0, 0x04, 0x94, 0x54, 0x22, 0x75, 0x68, 0xc4,
0x52, 0x09, 0x73, 0x03, 0x61, 0xe9, 0x97, 0x3f, 0x88, 0x11, 0xd9, 0x89, 0x31, 0x42, 0x38, 0x49, 0xc5, 0x97, 0xff, 0xc4, 0x7e, 0xf5, 0xc3, 0x4d, 0x2a, 0x61, 0x6e, 0x20, 0x2c, 0xfd, 0xf2, 0x07,
0x10, 0xc5, 0xbe, 0x86, 0x4d, 0x27, 0x30, 0x82, 0x00, 0x9a, 0x16, 0x83, 0x9e, 0x21, 0x3e, 0x06, 0x31, 0x22, 0x3b, 0x31, 0x46, 0x08, 0x27, 0x09, 0xa2, 0xd8, 0x37, 0xb0, 0xe9, 0x04, 0x46, 0x10,
0x6b, 0xc8, 0x8d, 0xad, 0x86, 0xdd, 0x54, 0x8b, 0xf1, 0x41, 0x10, 0x3b, 0xc7, 0x22, 0x73, 0x2a, 0x40, 0xd3, 0x62, 0xd0, 0x33, 0xc4, 0xc7, 0x60, 0x0d, 0xb9, 0xb1, 0xd5, 0xb0, 0x9b, 0x6a, 0x31,
0xc1, 0x1f, 0xc2, 0x52, 0x72, 0x50, 0x4e, 0x23, 0xf9, 0x3e, 0x86, 0xa2, 0x9f, 0x50, 0x2a, 0xcf, 0x3e, 0x08, 0x62, 0xe7, 0x58, 0x64, 0x4e, 0x25, 0xf8, 0x43, 0x58, 0x4a, 0x0e, 0xca, 0x69, 0x24,
0xaf, 0x25, 0x28, 0xec, 0xed, 0x1f, 0x3c, 0x5d, 0xdf, 0x68, 0xd6, 0xb4, 0xb5, 0x7f, 0x64, 0x21, 0xdf, 0xc7, 0x50, 0xf4, 0x13, 0x4a, 0xe5, 0x85, 0xb6, 0x04, 0x85, 0xbd, 0xfd, 0x83, 0xa7, 0xeb,
0xb3, 0xf3, 0x1c, 0x7d, 0x03, 0x72, 0xfc, 0xe1, 0x65, 0xc2, 0xbb, 0x54, 0x63, 0xd2, 0x13, 0x0e, 0x1b, 0xcd, 0x9a, 0xb6, 0xf6, 0x8f, 0x2c, 0x64, 0x76, 0x9e, 0xa3, 0x6f, 0x41, 0x8e, 0x3f, 0xbc,
0xbe, 0xfa, 0xe9, 0x1f, 0xff, 0xf2, 0x45, 0xe6, 0x12, 0xbe, 0xb0, 0x3a, 0x7a, 0xcb, 0xe8, 0x0d, 0x4c, 0x78, 0x97, 0x6a, 0x4c, 0x7a, 0xc2, 0xc1, 0x57, 0x3f, 0xfd, 0xe3, 0x5f, 0xbe, 0xc8, 0x5c,
0x8e, 0x8d, 0xd5, 0x93, 0xd1, 0x2a, 0x3b, 0x13, 0x1e, 0x6a, 0xf7, 0xd1, 0x73, 0xc8, 0x3e, 0x1d, 0xc2, 0x17, 0x56, 0x47, 0x6f, 0x19, 0xbd, 0xc1, 0xb1, 0xb1, 0x7a, 0x32, 0x5a, 0x65, 0x67, 0xc2,
0x7a, 0x28, 0xf1, 0xd1, 0xaa, 0x91, 0xfc, 0xb4, 0x83, 0x1b, 0x4c, 0xf2, 0x3c, 0x9e, 0x55, 0x25, 0x43, 0xed, 0x3e, 0x7a, 0x0e, 0xd9, 0xa7, 0x43, 0x0f, 0x25, 0x3e, 0x5a, 0x35, 0x92, 0x9f, 0x76,
0x0f, 0x86, 0x1e, 0x95, 0x3b, 0x82, 0x92, 0xf2, 0x3a, 0x83, 0xce, 0x7d, 0xce, 0x6a, 0x9c, 0xff, 0x70, 0x83, 0x49, 0x9e, 0xc7, 0xb3, 0xaa, 0xe4, 0xc1, 0xd0, 0xa3, 0x72, 0x47, 0x50, 0x52, 0x5e,
0xf2, 0x83, 0x31, 0xc3, 0xbb, 0x8a, 0x2f, 0xab, 0x78, 0xfc, 0x11, 0x49, 0x9d, 0xcf, 0xe1, 0xa9, 0x67, 0xd0, 0xb9, 0xcf, 0x59, 0x8d, 0xf3, 0x5f, 0x7e, 0x30, 0x66, 0x78, 0x57, 0xf1, 0x65, 0x15,
0x15, 0x9d, 0x4f, 0xf0, 0xc0, 0x10, 0x9d, 0x8f, 0x52, 0xd4, 0x8f, 0x9f, 0x8f, 0x77, 0x6a, 0x51, 0x8f, 0x3f, 0x22, 0xa9, 0xf3, 0x39, 0x3c, 0xb5, 0xa2, 0xf3, 0x09, 0x1e, 0x18, 0xa2, 0xf3, 0x51,
0xb9, 0xb6, 0x78, 0x51, 0x6a, 0x7b, 0xe8, 0x7a, 0xcc, 0x8b, 0x84, 0x5a, 0x7b, 0x6f, 0x2c, 0x25, 0x8a, 0xfa, 0xf1, 0xf3, 0xf1, 0x4e, 0x2d, 0x2a, 0xd7, 0x16, 0x2f, 0x4a, 0x6d, 0x0f, 0x5d, 0x8f,
0x33, 0x08, 0xa4, 0x1b, 0x0c, 0xe9, 0x0a, 0xbe, 0xa4, 0x22, 0xb5, 0x7d, 0xbe, 0x87, 0xda, 0xfd, 0x79, 0x91, 0x50, 0x6b, 0xef, 0x8d, 0xa5, 0x64, 0x06, 0x81, 0x74, 0x83, 0x21, 0x5d, 0xc1, 0x97,
0xb5, 0x63, 0xc8, 0xb1, 0x8a, 0x21, 0x6a, 0xc9, 0x8f, 0x46, 0x4c, 0xad, 0x33, 0x61, 0x07, 0x84, 0x54, 0xa4, 0xb6, 0xcf, 0xf7, 0x50, 0xbb, 0xbf, 0x76, 0x0c, 0x39, 0x56, 0x31, 0x44, 0x2d, 0xf9,
0x6a, 0x8d, 0x78, 0x81, 0xa1, 0xcd, 0xe1, 0xaa, 0x8f, 0xc6, 0x8a, 0x86, 0x0f, 0xb5, 0xfb, 0xcb, 0xd1, 0x88, 0xa9, 0x75, 0x26, 0xec, 0x80, 0x50, 0xad, 0x11, 0x2f, 0x30, 0xb4, 0x39, 0x5c, 0xf5,
0xda, 0x1b, 0xda, 0xda, 0x77, 0xa7, 0x21, 0xc7, 0x2a, 0x35, 0x68, 0x00, 0x10, 0xd4, 0xe0, 0xa2, 0xd1, 0x58, 0xd1, 0xf0, 0xa1, 0x76, 0x7f, 0x59, 0x7b, 0x43, 0x5b, 0xfb, 0xfe, 0x34, 0xe4, 0x58,
0xf3, 0x1c, 0xab, 0xea, 0x45, 0xe7, 0x39, 0x5e, 0xbe, 0xc3, 0xd7, 0x19, 0xf2, 0x02, 0x9e, 0xf7, 0xa5, 0x06, 0x0d, 0x00, 0x82, 0x1a, 0x5c, 0x74, 0x9e, 0x63, 0x55, 0xbd, 0xe8, 0x3c, 0xc7, 0xcb,
0x91, 0xd9, 0x43, 0xf9, 0x2a, 0xab, 0xc9, 0x50, 0xb3, 0xbe, 0x84, 0x92, 0x52, 0x4b, 0x43, 0x71, 0x77, 0xf8, 0x3a, 0x43, 0x5e, 0xc0, 0xf3, 0x3e, 0x32, 0x7b, 0xff, 0x5e, 0x65, 0x35, 0x19, 0x6a,
0x12, 0x43, 0xc5, 0xb8, 0xe8, 0x36, 0x89, 0x29, 0xc4, 0xe1, 0x9b, 0x0c, 0xf4, 0x1a, 0xae, 0xab, 0xd6, 0x97, 0x50, 0x52, 0x6a, 0x69, 0x28, 0x4e, 0x62, 0xa8, 0x18, 0x17, 0xdd, 0x26, 0x31, 0x85,
0xc6, 0xe5, 0xb8, 0x0e, 0xe3, 0xa4, 0xc0, 0x9f, 0x69, 0x50, 0x0d, 0xd7, 0xd3, 0xd0, 0xcd, 0x18, 0x38, 0x7c, 0x93, 0x81, 0x5e, 0xc3, 0x75, 0xd5, 0xb8, 0x1c, 0xd7, 0x61, 0x9c, 0x14, 0xf8, 0x33,
0xd1, 0xd1, 0xb2, 0x5c, 0xe3, 0xd6, 0x64, 0xa6, 0x44, 0x15, 0x38, 0xfe, 0x09, 0x21, 0x03, 0x83, 0x0d, 0xaa, 0xe1, 0x7a, 0x1a, 0xba, 0x19, 0x23, 0x3a, 0x5a, 0x96, 0x6b, 0xdc, 0x9a, 0xcc, 0x94,
0x72, 0x0a, 0xdb, 0xa3, 0xef, 0x6b, 0x30, 0x1b, 0xa9, 0x92, 0xa1, 0x38, 0x88, 0xb1, 0x1a, 0x5c, 0xa8, 0x02, 0xc7, 0x3f, 0x21, 0x64, 0x60, 0x50, 0x4e, 0x61, 0x7b, 0xf4, 0x03, 0x0d, 0x66, 0x23,
0xe3, 0xf6, 0x39, 0x5c, 0x42, 0x93, 0xbb, 0x4c, 0x93, 0x1b, 0xf8, 0xea, 0xb8, 0x31, 0x3c, 0xb3, 0x55, 0x32, 0x14, 0x07, 0x31, 0x56, 0x83, 0x6b, 0xdc, 0x3e, 0x87, 0x4b, 0x68, 0x72, 0x97, 0x69,
0x4f, 0x3c, 0x5b, 0x68, 0xb3, 0xf6, 0xcf, 0x2c, 0x14, 0x36, 0xf8, 0x2f, 0x91, 0x90, 0x07, 0x45, 0x72, 0x03, 0x5f, 0x1d, 0x37, 0x86, 0x67, 0xf6, 0x89, 0x67, 0x0b, 0x6d, 0xd6, 0xfe, 0x99, 0x85,
0xbf, 0xf2, 0x84, 0x16, 0xe3, 0xaa, 0x12, 0x41, 0xca, 0xde, 0xb8, 0x9e, 0xd8, 0x2f, 0x54, 0xb8, 0xc2, 0x06, 0xff, 0xb1, 0x12, 0xf2, 0xa0, 0xe8, 0x57, 0x9e, 0xd0, 0x62, 0x5c, 0x55, 0x22, 0x48,
0xc3, 0x54, 0x58, 0xc2, 0x57, 0x7c, 0x15, 0xc4, 0x2f, 0x9e, 0x56, 0xf9, 0xe5, 0x7b, 0xd5, 0xe8, 0xd9, 0x1b, 0xd7, 0x13, 0xfb, 0x85, 0x0a, 0x77, 0x98, 0x0a, 0x4b, 0xf8, 0x8a, 0xaf, 0x82, 0xf8,
0x74, 0xe8, 0x92, 0x7c, 0x47, 0x83, 0xb2, 0x5a, 0x50, 0x42, 0x37, 0x62, 0xeb, 0x21, 0x6a, 0x4d, 0x51, 0xd4, 0x2a, 0xbf, 0x7c, 0xaf, 0x1a, 0x9d, 0x0e, 0x5d, 0x92, 0xef, 0x69, 0x50, 0x56, 0x0b,
0xaa, 0x81, 0x27, 0xb1, 0x08, 0xfc, 0x7b, 0x0c, 0xff, 0x26, 0x5e, 0x4c, 0xc2, 0x77, 0x18, 0x7f, 0x4a, 0xe8, 0x46, 0x6c, 0x3d, 0x44, 0xad, 0x49, 0x35, 0xf0, 0x24, 0x16, 0x81, 0x7f, 0x8f, 0xe1,
0x58, 0x05, 0x5e, 0x42, 0x8a, 0x57, 0x21, 0x54, 0xa1, 0x8a, 0x57, 0x21, 0x5c, 0x81, 0x3a, 0x5f, 0xdf, 0xc4, 0x8b, 0x49, 0xf8, 0x0e, 0xe3, 0x0f, 0xab, 0xc0, 0x4b, 0x48, 0xf1, 0x2a, 0x84, 0x2a,
0x85, 0x21, 0xe3, 0xa7, 0x2a, 0x9c, 0x02, 0x04, 0x15, 0x26, 0x14, 0x6b, 0x5c, 0xe5, 0x12, 0x13, 0x54, 0xf1, 0x2a, 0x84, 0x2b, 0x50, 0xe7, 0xab, 0x30, 0x64, 0xfc, 0x54, 0x85, 0x53, 0x80, 0xa0,
0xf5, 0xc1, 0xf1, 0xe2, 0x54, 0xcc, 0x0e, 0x88, 0x60, 0xf7, 0x4c, 0x97, 0xfa, 0xe2, 0xda, 0x6f, 0xc2, 0x84, 0x62, 0x8d, 0xab, 0x5c, 0x62, 0xa2, 0x3e, 0x38, 0x5e, 0x9c, 0x8a, 0xd9, 0x01, 0x11,
0xa6, 0xa1, 0xf4, 0xc4, 0x30, 0x2d, 0x8f, 0x58, 0x86, 0xd5, 0x26, 0xa8, 0x0b, 0x39, 0x76, 0x4a, 0xec, 0x9e, 0xe9, 0x52, 0x5f, 0x5c, 0xfb, 0xcd, 0x34, 0x94, 0x9e, 0x18, 0xa6, 0xe5, 0x11, 0xcb,
0x45, 0x03, 0x8f, 0x5a, 0xf6, 0x89, 0x06, 0x9e, 0x50, 0x4d, 0x04, 0xdf, 0x66, 0xd0, 0xd7, 0x71, 0xb0, 0xda, 0x04, 0x75, 0x21, 0xc7, 0x4e, 0xa9, 0x68, 0xe0, 0x51, 0xcb, 0x3e, 0xd1, 0xc0, 0x13,
0xc3, 0x87, 0xee, 0x07, 0xf2, 0x57, 0x59, 0x3d, 0x83, 0x4e, 0xf9, 0x04, 0xf2, 0xbc, 0x7e, 0x81, 0xaa, 0x89, 0xe0, 0xdb, 0x0c, 0xfa, 0x3a, 0x6e, 0xf8, 0xd0, 0xfd, 0x40, 0xfe, 0x2a, 0xab, 0x67,
0x22, 0xd2, 0x42, 0x75, 0x8e, 0xc6, 0xd5, 0xf8, 0xce, 0xc4, 0x5d, 0xa6, 0x62, 0xb9, 0x8c, 0x99, 0xd0, 0x29, 0x9f, 0x40, 0x9e, 0xd7, 0x2f, 0x50, 0x44, 0x5a, 0xa8, 0xce, 0xd1, 0xb8, 0x1a, 0xdf,
0x82, 0x7d, 0x13, 0x20, 0x28, 0x98, 0x45, 0xed, 0x3b, 0x56, 0x5f, 0x6b, 0x2c, 0x25, 0x33, 0x08, 0x99, 0xb8, 0xcb, 0x54, 0x2c, 0x97, 0x31, 0x53, 0xb0, 0x6f, 0x03, 0x04, 0x05, 0xb3, 0xa8, 0x7d,
0xe0, 0xfb, 0x0c, 0xf8, 0x16, 0xbe, 0x1e, 0x0b, 0xdc, 0xf1, 0x07, 0x50, 0xf0, 0x36, 0x4c, 0x6f, 0xc7, 0xea, 0x6b, 0x8d, 0xa5, 0x64, 0x06, 0x01, 0x7c, 0x9f, 0x01, 0xdf, 0xc2, 0xd7, 0x63, 0x81,
0x19, 0xee, 0x31, 0x8a, 0x1c, 0x42, 0xca, 0x2b, 0x69, 0xa3, 0x11, 0xd7, 0x25, 0xa0, 0x6e, 0x31, 0x3b, 0xfe, 0x00, 0x0a, 0xde, 0x86, 0xe9, 0x2d, 0xc3, 0x3d, 0x46, 0x91, 0x43, 0x48, 0x79, 0x25,
0xa8, 0x45, 0xbc, 0x10, 0x0b, 0x75, 0x6c, 0xb8, 0x34, 0xa6, 0xa3, 0x21, 0xcc, 0xc8, 0x97, 0x4f, 0x6d, 0x34, 0xe2, 0xba, 0x04, 0xd4, 0x2d, 0x06, 0xb5, 0x88, 0x17, 0x62, 0xa1, 0x8e, 0x0d, 0x97,
0x74, 0x2d, 0x62, 0xb3, 0xf0, 0x2b, 0x69, 0x63, 0x31, 0xa9, 0x5b, 0x00, 0x2e, 0x33, 0x40, 0x8c, 0xc6, 0x74, 0x34, 0x84, 0x19, 0xf9, 0xf2, 0x89, 0xae, 0x45, 0x6c, 0x16, 0x7e, 0x25, 0x6d, 0x2c,
0xaf, 0xc5, 0x1b, 0x55, 0xb0, 0x3f, 0xd4, 0xee, 0xbf, 0xa1, 0xad, 0xfd, 0xb0, 0x06, 0xd3, 0x34, 0x26, 0x75, 0x0b, 0xc0, 0x65, 0x06, 0x88, 0xf1, 0xb5, 0x78, 0xa3, 0x0a, 0xf6, 0x87, 0xda, 0xfd,
0x5f, 0xa2, 0xa7, 0x48, 0x70, 0xcd, 0x8c, 0x5a, 0x78, 0xac, 0xb8, 0x13, 0xb5, 0xf0, 0xf8, 0x0d, 0x37, 0xb4, 0xb5, 0x1f, 0xd5, 0x60, 0x9a, 0xe6, 0x4b, 0xf4, 0x14, 0x09, 0xae, 0x99, 0x51, 0x0b,
0x35, 0xe6, 0x14, 0x61, 0xbf, 0xc7, 0x24, 0x8c, 0x8b, 0xce, 0xd8, 0x83, 0x92, 0x72, 0x19, 0x45, 0x8f, 0x15, 0x77, 0xa2, 0x16, 0x1e, 0xbf, 0xa1, 0xc6, 0x9c, 0x22, 0xec, 0x27, 0x9b, 0x84, 0x71,
0x31, 0x12, 0xc3, 0xa5, 0xa3, 0xe8, 0x29, 0x12, 0x73, 0x93, 0xc5, 0x4b, 0x0c, 0xb4, 0x81, 0x2f, 0xd1, 0x19, 0x7b, 0x50, 0x52, 0x2e, 0xa3, 0x28, 0x46, 0x62, 0xb8, 0x74, 0x14, 0x3d, 0x45, 0x62,
0x86, 0x41, 0x3b, 0x9c, 0x8d, 0xa2, 0x7e, 0x0b, 0xca, 0xea, 0xad, 0x15, 0xc5, 0x08, 0x8d, 0xd4, 0x6e, 0xb2, 0x78, 0x89, 0x81, 0x36, 0xf0, 0xc5, 0x30, 0x68, 0x87, 0xb3, 0x51, 0xd4, 0xef, 0x40,
0xa6, 0xa2, 0xb1, 0x22, 0xee, 0xd2, 0x1b, 0xe3, 0x34, 0xfe, 0xaf, 0x4f, 0x25, 0x2f, 0x45, 0xff, 0x59, 0xbd, 0xb5, 0xa2, 0x18, 0xa1, 0x91, 0xda, 0x54, 0x34, 0x56, 0xc4, 0x5d, 0x7a, 0x63, 0x9c,
0x18, 0x0a, 0xe2, 0x2e, 0x1b, 0x37, 0xdf, 0x70, 0x35, 0x2b, 0x6e, 0xbe, 0x91, 0x8b, 0x70, 0x4c, 0xc6, 0xff, 0x81, 0xaa, 0xe4, 0xa5, 0xe8, 0x1f, 0x43, 0x41, 0xdc, 0x65, 0xe3, 0xe6, 0x1b, 0xae,
0x4a, 0xc2, 0x60, 0x69, 0xce, 0x2e, 0x03, 0xb4, 0x80, 0x7c, 0x4c, 0xbc, 0x24, 0xc8, 0xa0, 0x3e, 0x66, 0xc5, 0xcd, 0x37, 0x72, 0x11, 0x8e, 0x49, 0x49, 0x18, 0x2c, 0xcd, 0xd9, 0x65, 0x80, 0x16,
0x93, 0x04, 0xa9, 0xdc, 0x97, 0x26, 0x42, 0x76, 0x89, 0x27, 0xf6, 0xb2, 0xbc, 0x8c, 0xa0, 0x04, 0x90, 0x8f, 0x89, 0x97, 0x04, 0x19, 0xd4, 0x67, 0x92, 0x20, 0x95, 0xfb, 0xd2, 0x44, 0xc8, 0x2e,
0x89, 0x6a, 0x34, 0xc4, 0x93, 0x58, 0x12, 0xb3, 0xc8, 0x00, 0x55, 0x84, 0x42, 0xf4, 0x6d, 0x80, 0xf1, 0xc4, 0x5e, 0x96, 0x97, 0x11, 0x94, 0x20, 0x51, 0x8d, 0x86, 0x78, 0x12, 0x4b, 0x62, 0x16,
0xe0, 0xe2, 0x1d, 0x4d, 0x0c, 0x62, 0xab, 0x77, 0xd1, 0xc4, 0x20, 0xfe, 0xee, 0x1e, 0xe3, 0xc1, 0x19, 0xa0, 0x8a, 0x50, 0x88, 0xbe, 0x0b, 0x10, 0x5c, 0xbc, 0xa3, 0x89, 0x41, 0x6c, 0xf5, 0x2e,
0x01, 0x38, 0xcf, 0x64, 0x29, 0xfc, 0x8f, 0x35, 0x40, 0xe3, 0x17, 0x75, 0xf4, 0x20, 0x1e, 0x22, 0x9a, 0x18, 0xc4, 0xdf, 0xdd, 0x63, 0x3c, 0x38, 0x00, 0xe7, 0x99, 0x2c, 0x85, 0xff, 0x89, 0x06,
0xb6, 0x30, 0xd8, 0x78, 0xed, 0xd5, 0x98, 0x13, 0xa3, 0x67, 0xa0, 0x57, 0x9b, 0x0d, 0x19, 0xbc, 0x68, 0xfc, 0xa2, 0x8e, 0x1e, 0xc4, 0x43, 0xc4, 0x16, 0x06, 0x1b, 0xaf, 0xbd, 0x1a, 0x73, 0x62,
0xa4, 0x9a, 0x7d, 0xae, 0x41, 0x25, 0x74, 0xd5, 0x47, 0x77, 0x12, 0xd6, 0x39, 0x52, 0x5c, 0x6c, 0xf4, 0x0c, 0xf4, 0x6a, 0xb3, 0x21, 0x83, 0x97, 0x54, 0xb3, 0xcf, 0x35, 0xa8, 0x84, 0xae, 0xfa,
0xdc, 0x3d, 0x97, 0x2f, 0x31, 0x77, 0x52, 0x76, 0x85, 0xcc, 0x1b, 0x7f, 0xa0, 0x41, 0x35, 0x5c, 0xe8, 0x4e, 0xc2, 0x3a, 0x47, 0x8a, 0x8b, 0x8d, 0xbb, 0xe7, 0xf2, 0x25, 0xe6, 0x4e, 0xca, 0xae,
0x1f, 0x40, 0x09, 0x00, 0x63, 0x15, 0xca, 0xc6, 0xf2, 0xf9, 0x8c, 0xaf, 0xb0, 0x5a, 0x41, 0x2a, 0x90, 0x79, 0xe3, 0x0f, 0x35, 0xa8, 0x86, 0xeb, 0x03, 0x28, 0x01, 0x60, 0xac, 0x42, 0xd9, 0x58,
0xf9, 0x31, 0x14, 0x44, 0x59, 0x21, 0xce, 0x2d, 0xc2, 0x05, 0xce, 0x38, 0xb7, 0x88, 0xd4, 0x24, 0x3e, 0x9f, 0xf1, 0x15, 0x56, 0x2b, 0x48, 0x25, 0x3f, 0x86, 0x82, 0x28, 0x2b, 0xc4, 0xb9, 0x45,
0x92, 0xdc, 0x82, 0xde, 0xd0, 0x15, 0x4f, 0x14, 0xc5, 0x87, 0x24, 0xc8, 0xc9, 0x9e, 0x18, 0xa9, 0xb8, 0xc0, 0x19, 0xe7, 0x16, 0x91, 0x9a, 0x44, 0x92, 0x5b, 0xd0, 0x1b, 0xba, 0xe2, 0x89, 0xa2,
0x5c, 0x4c, 0x84, 0x0c, 0x3c, 0x51, 0x96, 0x1e, 0x50, 0x82, 0xc4, 0x73, 0x3c, 0x31, 0x5a, 0xb9, 0xf8, 0x90, 0x04, 0x39, 0xd9, 0x13, 0x23, 0x95, 0x8b, 0x89, 0x90, 0x81, 0x27, 0xca, 0xd2, 0x03,
0x48, 0xf2, 0x44, 0x86, 0xaa, 0x78, 0x62, 0x50, 0x29, 0x88, 0xf3, 0xc4, 0xb1, 0xf2, 0x6d, 0x9c, 0x4a, 0x90, 0x78, 0x8e, 0x27, 0x46, 0x2b, 0x17, 0x49, 0x9e, 0xc8, 0x50, 0x15, 0x4f, 0x0c, 0x2a,
0x27, 0x8e, 0x17, 0x1b, 0x92, 0xd6, 0x96, 0x81, 0x87, 0x3c, 0x71, 0x2e, 0xa6, 0xb2, 0x80, 0x5e, 0x05, 0x71, 0x9e, 0x38, 0x56, 0xbe, 0x8d, 0xf3, 0xc4, 0xf1, 0x62, 0x43, 0xd2, 0xda, 0x32, 0xf0,
0x4b, 0xb0, 0x69, 0x6c, 0x69, 0xb8, 0xf1, 0xfa, 0x2b, 0x72, 0x4f, 0xf6, 0x00, 0xbe, 0x1a, 0xd2, 0x90, 0x27, 0xce, 0xc5, 0x54, 0x16, 0xd0, 0x6b, 0x09, 0x36, 0x8d, 0x2d, 0x0d, 0x37, 0x5e, 0x7f,
0x03, 0x7e, 0xae, 0xc1, 0x7c, 0x5c, 0x69, 0x02, 0x25, 0x80, 0x25, 0xd4, 0x95, 0x1b, 0x2b, 0xaf, 0x45, 0xee, 0xc9, 0x1e, 0xc0, 0x57, 0x43, 0x7a, 0xc0, 0x2f, 0x34, 0x98, 0x8f, 0x2b, 0x4d, 0xa0,
0xca, 0xfe, 0x0a, 0x76, 0xf3, 0x7d, 0xe2, 0x51, 0xed, 0xb7, 0x5f, 0x2e, 0x6a, 0x7f, 0xf8, 0x72, 0x04, 0xb0, 0x84, 0xba, 0x72, 0x63, 0xe5, 0x55, 0xd9, 0x5f, 0xc1, 0x6e, 0xbe, 0x4f, 0x3c, 0xaa,
0x51, 0xfb, 0xd3, 0x97, 0x8b, 0xda, 0x4f, 0xfe, 0xbc, 0x38, 0x75, 0x94, 0x67, 0xff, 0x29, 0xe2, 0xfd, 0xf6, 0xab, 0x45, 0xed, 0x0f, 0x5f, 0x2d, 0x6a, 0x7f, 0xfa, 0x6a, 0x51, 0xfb, 0xe9, 0x9f,
0xad, 0x7f, 0x05, 0x00, 0x00, 0xff, 0xff, 0x89, 0x96, 0x81, 0x80, 0x9b, 0x31, 0x00, 0x00, 0x17, 0xa7, 0x8e, 0xf2, 0xec, 0xff, 0x4d, 0xbc, 0xf5, 0xaf, 0x00, 0x00, 0x00, 0xff, 0xff, 0x10,
0xb3, 0xfb, 0x25, 0xbe, 0x31, 0x00, 0x00,
} }

View File

@ -427,6 +427,10 @@ message PutRequest {
// If ignore_value is set, etcd updates the key using its current value. // If ignore_value is set, etcd updates the key using its current value.
// Returns an error if the key does not exist. // Returns an error if the key does not exist.
bool ignore_value = 5; bool ignore_value = 5;
// If ignore_lease is set, etcd updates the key using its current lease.
// Returns an error if the key does not exist.
bool ignore_lease = 6;
} }
message PutResponse { message PutResponse {

View File

@ -395,7 +395,7 @@ func TestV3PutIgnoreValue(t *testing.T) {
_, err := kvc.Put(context.TODO(), &preq) _, err := kvc.Put(context.TODO(), &preq)
return err return err
}, },
rpctypes.ErrGRPCValue, rpctypes.ErrGRPCValueProvided,
0, 0,
}, },
{ // overwrite with previous value, ensure no prev-kv is returned and lease is detached { // overwrite with previous value, ensure no prev-kv is returned and lease is detached
@ -448,6 +448,146 @@ func TestV3PutIgnoreValue(t *testing.T) {
} }
} }
// TestV3PutIgnoreLease ensures that writes with ignore_lease uses previous lease for the key overwrites.
func TestV3PutIgnoreLease(t *testing.T) {
defer testutil.AfterTest(t)
clus := NewClusterV3(t, &ClusterConfig{Size: 1})
defer clus.Terminate(t)
kvc := toGRPC(clus.RandClient()).KV
// create lease
lc := toGRPC(clus.RandClient()).Lease
lresp, err := lc.LeaseGrant(context.TODO(), &pb.LeaseGrantRequest{TTL: 30})
if err != nil {
t.Fatal(err)
}
if lresp.Error != "" {
t.Fatal(lresp.Error)
}
key, val, val1 := []byte("zoo"), []byte("bar"), []byte("bar1")
putReq := pb.PutRequest{Key: key, Value: val}
tests := []struct {
putFunc func() error
putErr error
wleaseID int64
wvalue []byte
}{
{ // put failure for non-existent key
func() error {
preq := putReq
preq.IgnoreLease = true
_, err := kvc.Put(context.TODO(), &preq)
return err
},
rpctypes.ErrGRPCKeyNotFound,
0,
nil,
},
{ // txn failure for non-existent key
func() error {
preq := putReq
preq.IgnoreLease = true
txn := &pb.TxnRequest{}
txn.Success = append(txn.Success, &pb.RequestOp{
Request: &pb.RequestOp_RequestPut{RequestPut: &preq}})
_, err := kvc.Txn(context.TODO(), txn)
return err
},
rpctypes.ErrGRPCKeyNotFound,
0,
nil,
},
{ // put success
func() error {
preq := putReq
preq.Lease = lresp.ID
_, err := kvc.Put(context.TODO(), &preq)
return err
},
nil,
lresp.ID,
val,
},
{ // txn success, modify value using 'ignore_lease' and ensure lease is not detached
func() error {
preq := putReq
preq.Value = val1
preq.IgnoreLease = true
txn := &pb.TxnRequest{}
txn.Success = append(txn.Success, &pb.RequestOp{
Request: &pb.RequestOp_RequestPut{RequestPut: &preq}})
_, err := kvc.Txn(context.TODO(), txn)
return err
},
nil,
lresp.ID,
val1,
},
{ // non-empty lease with ignore_lease should error
func() error {
preq := putReq
preq.Lease = lresp.ID
preq.IgnoreLease = true
_, err := kvc.Put(context.TODO(), &preq)
return err
},
rpctypes.ErrGRPCLeaseProvided,
0,
nil,
},
{ // overwrite with previous value, ensure no prev-kv is returned and lease is detached
func() error {
presp, err := kvc.Put(context.TODO(), &putReq)
if err != nil {
return err
}
if presp.PrevKv != nil && len(presp.PrevKv.Key) != 0 {
return fmt.Errorf("unexexpected previous key-value %v", presp.PrevKv)
}
return nil
},
nil,
0,
val,
},
{ // revoke lease, ensure detached key doesn't get deleted
func() error {
_, err := lc.LeaseRevoke(context.TODO(), &pb.LeaseRevokeRequest{ID: lresp.ID})
return err
},
nil,
0,
val,
},
}
for i, tt := range tests {
if err := tt.putFunc(); !eqErrGRPC(err, tt.putErr) {
t.Fatalf("#%d: err expected %v, got %v", i, tt.putErr, err)
}
if tt.putErr != nil {
continue
}
rr, err := kvc.Range(context.TODO(), &pb.RangeRequest{Key: key})
if err != nil {
t.Fatalf("#%d: %v", i, err)
}
if len(rr.Kvs) != 1 {
t.Fatalf("#%d: len(rr.KVs) expected 1, got %d", i, len(rr.Kvs))
}
if !bytes.Equal(rr.Kvs[0].Value, tt.wvalue) {
t.Fatalf("#%d: value expected %q, got %q", i, val, rr.Kvs[0].Value)
}
if rr.Kvs[0].Lease != tt.wleaseID {
t.Fatalf("#%d: lease ID expected %d, got %d", i, tt.wleaseID, rr.Kvs[0].Lease)
}
}
}
// TestV3PutMissingLease ensures that a Put on a key with a bogus lease fails. // TestV3PutMissingLease ensures that a Put on a key with a bogus lease fails.
func TestV3PutMissingLease(t *testing.T) { func TestV3PutMissingLease(t *testing.T) {
defer testutil.AfterTest(t) defer testutil.AfterTest(t)

View File

@ -197,6 +197,9 @@ func PutRequestToOp(r *pb.PutRequest) clientv3.Op {
if r.IgnoreValue { if r.IgnoreValue {
opts = append(opts, clientv3.WithIgnoreValue()) opts = append(opts, clientv3.WithIgnoreValue())
} }
if r.IgnoreLease {
opts = append(opts, clientv3.WithIgnoreLease())
}
return clientv3.OpPut(string(r.Key), string(r.Value), opts...) return clientv3.OpPut(string(r.Key), string(r.Value), opts...)
} }