*: support count in range query

This commit is contained in:
Xiang Li 2016-06-21 16:20:55 -07:00
parent c01c36bcfd
commit def21f11a9
8 changed files with 406 additions and 286 deletions

View File

@ -930,6 +930,11 @@
"etcdserverpbRangeRequest": { "etcdserverpbRangeRequest": {
"type": "object", "type": "object",
"properties": { "properties": {
"count_only": {
"type": "boolean",
"format": "boolean",
"description": "count_only when set returns only the count of the keys in the range."
},
"key": { "key": {
"type": "string", "type": "string",
"format": "byte", "format": "byte",
@ -973,6 +978,11 @@
"etcdserverpbRangeResponse": { "etcdserverpbRangeResponse": {
"type": "object", "type": "object",
"properties": { "properties": {
"count": {
"type": "string",
"format": "int64",
"description": "count is set to the number of keys within the range when requested."
},
"header": { "header": {
"$ref": "#/definitions/etcdserverpbResponseHeader" "$ref": "#/definitions/etcdserverpbResponseHeader"
}, },
@ -981,7 +991,7 @@
"items": { "items": {
"$ref": "#/definitions/mvccpbKeyValue" "$ref": "#/definitions/mvccpbKeyValue"
}, },
"description": "kvs is the list of key-value pairs matched by the range request." "description": "kvs is the list of key-value pairs matched by the range request.\nkvs is empty when count is requested."
}, },
"more": { "more": {
"type": "boolean", "type": "boolean",

View File

@ -210,8 +210,7 @@ func (a *applierV3backend) Range(txnID int64, r *pb.RangeRequest) (*pb.RangeResp
resp.Header = &pb.ResponseHeader{} resp.Header = &pb.ResponseHeader{}
var ( var (
kvs []mvccpb.KeyValue rr *mvcc.RangeResult
rev int64
err error err error
) )
@ -229,13 +228,19 @@ func (a *applierV3backend) Range(txnID int64, r *pb.RangeRequest) (*pb.RangeResp
limit = limit + 1 limit = limit + 1
} }
ro := mvcc.RangeOptions{
Limit: limit,
Rev: r.Revision,
Count: r.CountOnly,
}
if txnID != noTxn { if txnID != noTxn {
kvs, rev, err = a.s.KV().TxnRange(txnID, r.Key, r.RangeEnd, limit, r.Revision) rr, err = a.s.KV().TxnRange(txnID, r.Key, r.RangeEnd, ro)
if err != nil { if err != nil {
return nil, err return nil, err
} }
} else { } else {
kvs, rev, err = a.s.KV().Range(r.Key, r.RangeEnd, limit, r.Revision) rr, err = a.s.KV().Range(r.Key, r.RangeEnd, ro)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -245,15 +250,15 @@ func (a *applierV3backend) Range(txnID int64, r *pb.RangeRequest) (*pb.RangeResp
var sorter sort.Interface var sorter sort.Interface
switch { switch {
case r.SortTarget == pb.RangeRequest_KEY: case r.SortTarget == pb.RangeRequest_KEY:
sorter = &kvSortByKey{&kvSort{kvs}} sorter = &kvSortByKey{&kvSort{rr.KVs}}
case r.SortTarget == pb.RangeRequest_VERSION: case r.SortTarget == pb.RangeRequest_VERSION:
sorter = &kvSortByVersion{&kvSort{kvs}} sorter = &kvSortByVersion{&kvSort{rr.KVs}}
case r.SortTarget == pb.RangeRequest_CREATE: case r.SortTarget == pb.RangeRequest_CREATE:
sorter = &kvSortByCreate{&kvSort{kvs}} sorter = &kvSortByCreate{&kvSort{rr.KVs}}
case r.SortTarget == pb.RangeRequest_MOD: case r.SortTarget == pb.RangeRequest_MOD:
sorter = &kvSortByMod{&kvSort{kvs}} sorter = &kvSortByMod{&kvSort{rr.KVs}}
case r.SortTarget == pb.RangeRequest_VALUE: case r.SortTarget == pb.RangeRequest_VALUE:
sorter = &kvSortByValue{&kvSort{kvs}} sorter = &kvSortByValue{&kvSort{rr.KVs}}
} }
switch { switch {
case r.SortOrder == pb.RangeRequest_ASCEND: case r.SortOrder == pb.RangeRequest_ASCEND:
@ -263,17 +268,18 @@ func (a *applierV3backend) Range(txnID int64, r *pb.RangeRequest) (*pb.RangeResp
} }
} }
if r.Limit > 0 && len(kvs) > int(r.Limit) { if r.Limit > 0 && len(rr.KVs) > int(r.Limit) {
kvs = kvs[:r.Limit] rr.KVs = rr.KVs[:r.Limit]
resp.More = true resp.More = true
} }
resp.Header.Revision = rev resp.Header.Revision = rr.Rev
for i := range kvs { resp.Count = int64(rr.Count)
for i := range rr.KVs {
if r.KeysOnly { if r.KeysOnly {
kvs[i].Value = nil rr.KVs[i].Value = nil
} }
resp.Kvs = append(resp.Kvs, &kvs[i]) resp.Kvs = append(resp.Kvs, &rr.KVs[i])
} }
return resp, nil return resp, nil
} }
@ -337,7 +343,9 @@ func (a *applierV3backend) Txn(rt *pb.TxnRequest) (*pb.TxnResponse, error) {
// It returns the revision at which the comparison happens. If the comparison // It returns the revision at which the comparison happens. If the comparison
// succeeds, the it returns true. Otherwise it returns false. // succeeds, the it returns true. Otherwise it returns false.
func (a *applierV3backend) applyCompare(c *pb.Compare) (int64, bool) { func (a *applierV3backend) applyCompare(c *pb.Compare) (int64, bool) {
ckvs, rev, err := a.s.KV().Range(c.Key, nil, 1, 0) rr, err := a.s.KV().Range(c.Key, nil, mvcc.RangeOptions{})
rev := rr.Rev
if err != nil { if err != nil {
if err == mvcc.ErrTxnIDMismatch { if err == mvcc.ErrTxnIDMismatch {
panic("unexpected txn ID mismatch error") panic("unexpected txn ID mismatch error")
@ -345,8 +353,8 @@ func (a *applierV3backend) applyCompare(c *pb.Compare) (int64, bool) {
return rev, false return rev, false
} }
var ckv mvccpb.KeyValue var ckv mvccpb.KeyValue
if len(ckvs) != 0 { if len(rr.KVs) != 0 {
ckv = ckvs[0] ckv = rr.KVs[0]
} else { } else {
// Use the zero value of ckv normally. However... // Use the zero value of ckv normally. However...
if c.Target == pb.Compare_VALUE { if c.Target == pb.Compare_VALUE {
@ -443,7 +451,8 @@ func (a *applierV3backend) Compaction(compaction *pb.CompactionRequest) (*pb.Com
return nil, ch, err return nil, ch, err
} }
// get the current revision. which key to get is not important. // get the current revision. which key to get is not important.
_, resp.Header.Revision, _ = a.s.KV().Range([]byte("compaction"), nil, 1, 0) rr, _ := a.s.KV().Range([]byte("compaction"), nil, mvcc.RangeOptions{})
resp.Header.Revision = rr.Rev
return resp, ch, err return resp, ch, err
} }

View File

@ -224,6 +224,8 @@ type RangeRequest struct {
Serializable bool `protobuf:"varint,7,opt,name=serializable,proto3" json:"serializable,omitempty"` Serializable bool `protobuf:"varint,7,opt,name=serializable,proto3" json:"serializable,omitempty"`
// keys_only when set returns only the keys and not the values. // keys_only when set returns only the keys and not the values.
KeysOnly bool `protobuf:"varint,8,opt,name=keys_only,json=keysOnly,proto3" json:"keys_only,omitempty"` KeysOnly bool `protobuf:"varint,8,opt,name=keys_only,json=keysOnly,proto3" json:"keys_only,omitempty"`
// count_only when set returns only the count of the keys in the range.
CountOnly bool `protobuf:"varint,9,opt,name=count_only,json=countOnly,proto3" json:"count_only,omitempty"`
} }
func (m *RangeRequest) Reset() { *m = RangeRequest{} } func (m *RangeRequest) Reset() { *m = RangeRequest{} }
@ -234,9 +236,12 @@ func (*RangeRequest) Descriptor() ([]byte, []int) { return fileDescriptorRpc, []
type RangeResponse struct { type RangeResponse struct {
Header *ResponseHeader `protobuf:"bytes,1,opt,name=header" json:"header,omitempty"` Header *ResponseHeader `protobuf:"bytes,1,opt,name=header" json:"header,omitempty"`
// kvs is the list of key-value pairs matched by the range request. // kvs is the list of key-value pairs matched by the range request.
// kvs is empty when count is requested.
Kvs []*mvccpb.KeyValue `protobuf:"bytes,2,rep,name=kvs" json:"kvs,omitempty"` Kvs []*mvccpb.KeyValue `protobuf:"bytes,2,rep,name=kvs" json:"kvs,omitempty"`
// more indicates if there are more keys to return in the requested range. // more indicates if there are more keys to return in the requested range.
More bool `protobuf:"varint,3,opt,name=more,proto3" json:"more,omitempty"` More bool `protobuf:"varint,3,opt,name=more,proto3" json:"more,omitempty"`
// count is set to the number of keys within the range when requested.
Count int64 `protobuf:"varint,4,opt,name=count,proto3" json:"count,omitempty"`
} }
func (m *RangeResponse) Reset() { *m = RangeResponse{} } func (m *RangeResponse) Reset() { *m = RangeResponse{} }
@ -3660,6 +3665,16 @@ func (m *RangeRequest) MarshalTo(data []byte) (int, error) {
} }
i++ i++
} }
if m.CountOnly {
data[i] = 0x48
i++
if m.CountOnly {
data[i] = 1
} else {
data[i] = 0
}
i++
}
return i, nil return i, nil
} }
@ -3710,6 +3725,11 @@ func (m *RangeResponse) MarshalTo(data []byte) (int, error) {
} }
i++ i++
} }
if m.Count != 0 {
data[i] = 0x20
i++
i = encodeVarintRpc(data, i, uint64(m.Count))
}
return i, nil return i, nil
} }
@ -6214,6 +6234,9 @@ func (m *RangeRequest) Size() (n int) {
if m.KeysOnly { if m.KeysOnly {
n += 2 n += 2
} }
if m.CountOnly {
n += 2
}
return n return n
} }
@ -6233,6 +6256,9 @@ func (m *RangeResponse) Size() (n int) {
if m.More { if m.More {
n += 2 n += 2
} }
if m.Count != 0 {
n += 1 + sovRpc(uint64(m.Count))
}
return n return n
} }
@ -7593,6 +7619,26 @@ func (m *RangeRequest) Unmarshal(data []byte) error {
} }
} }
m.KeysOnly = bool(v != 0) m.KeysOnly = bool(v != 0)
case 9:
if wireType != 0 {
return fmt.Errorf("proto: wrong wireType = %d for field CountOnly", 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.CountOnly = bool(v != 0)
default: default:
iNdEx = preIndex iNdEx = preIndex
skippy, err := skipRpc(data[iNdEx:]) skippy, err := skipRpc(data[iNdEx:])
@ -7727,6 +7773,25 @@ func (m *RangeResponse) Unmarshal(data []byte) error {
} }
} }
m.More = bool(v != 0) m.More = bool(v != 0)
case 4:
if wireType != 0 {
return fmt.Errorf("proto: wrong wireType = %d for field Count", wireType)
}
m.Count = 0
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowRpc
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := data[iNdEx]
iNdEx++
m.Count |= (int64(b) & 0x7F) << shift
if b < 0x80 {
break
}
}
default: default:
iNdEx = preIndex iNdEx = preIndex
skippy, err := skipRpc(data[iNdEx:]) skippy, err := skipRpc(data[iNdEx:])
@ -15060,199 +15125,200 @@ var (
) )
var fileDescriptorRpc = []byte{ var fileDescriptorRpc = []byte{
// 3097 bytes of a gzipped FileDescriptorProto // 3116 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0xb4, 0x5a, 0x4b, 0x73, 0x24, 0x47, 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0xb4, 0x5a, 0x4b, 0x73, 0x24, 0x47,
0xf1, 0xdf, 0x79, 0xe8, 0x31, 0x39, 0xa3, 0x59, 0x6d, 0x49, 0xbb, 0x1e, 0xf5, 0x6a, 0xb5, 0xda, 0x11, 0xde, 0x79, 0xe8, 0x31, 0x39, 0xa3, 0x59, 0x6d, 0x49, 0xbb, 0x1e, 0xf5, 0x6a, 0xb5, 0xda,
0xda, 0xa7, 0x5f, 0x9a, 0xbf, 0x65, 0xff, 0x39, 0x00, 0xe1, 0x88, 0x91, 0x66, 0x58, 0xcb, 0x92, 0xda, 0xa7, 0x5f, 0x1a, 0x2c, 0x1b, 0x0e, 0x40, 0x38, 0x62, 0xa4, 0x19, 0xd6, 0xb2, 0x64, 0x69,
0xa5, 0x75, 0x6b, 0x56, 0x36, 0x11, 0x04, 0x8a, 0xd6, 0x4c, 0xad, 0x34, 0xa1, 0x79, 0xb9, 0xbb, 0xdd, 0x9a, 0x95, 0x4d, 0x04, 0x81, 0xa2, 0x35, 0x53, 0x2b, 0x4d, 0x68, 0x5e, 0xee, 0xee, 0xd1,
0x47, 0x2b, 0x19, 0x1c, 0x41, 0x38, 0xf0, 0x01, 0xae, 0x3e, 0x10, 0xc0, 0x91, 0x4f, 0xc0, 0x81, 0x4a, 0x06, 0x22, 0x08, 0x07, 0x3e, 0xc0, 0xd5, 0x07, 0x02, 0x38, 0xf2, 0x1b, 0xb8, 0xf1, 0x03,
0x1b, 0x1f, 0x80, 0xe0, 0x02, 0x11, 0x1c, 0xb9, 0x10, 0x04, 0x07, 0x0e, 0xdc, 0x09, 0x4e, 0x50, 0x08, 0x2e, 0x38, 0x82, 0x23, 0x17, 0x82, 0xe0, 0xc0, 0x81, 0x3b, 0xc1, 0x09, 0xea, 0xd9, 0x5d,
0xcf, 0xee, 0xea, 0x9e, 0xea, 0x91, 0x4c, 0xe3, 0xc3, 0xae, 0xba, 0xb2, 0xb2, 0xf2, 0x97, 0x95, 0xdd, 0x53, 0x3d, 0x92, 0x69, 0x7c, 0xd8, 0x55, 0x57, 0x56, 0x56, 0x7e, 0x59, 0x59, 0x95, 0xd9,
0x55, 0x99, 0x9d, 0x99, 0x3d, 0x50, 0x70, 0x87, 0xad, 0xb5, 0xa1, 0x3b, 0xf0, 0x07, 0xa8, 0x44, 0x99, 0xd9, 0x03, 0x05, 0x77, 0xd8, 0x5a, 0x1b, 0xba, 0x03, 0x7f, 0x80, 0x4a, 0xc4, 0x6f, 0xb5,
0xfc, 0x56, 0xdb, 0x23, 0xee, 0x19, 0x71, 0x87, 0x47, 0xd6, 0xe2, 0xf1, 0xe0, 0x78, 0xc0, 0x27, 0x3d, 0xe2, 0x9e, 0x11, 0x77, 0x78, 0x64, 0x2d, 0x1e, 0x0f, 0x8e, 0x07, 0x7c, 0xa2, 0xca, 0x9e,
0xaa, 0xec, 0x49, 0xf0, 0x58, 0x4b, 0x8c, 0xa7, 0xda, 0x3b, 0x6b, 0xb5, 0xf8, 0x7f, 0xc3, 0xa3, 0x04, 0x8f, 0xb5, 0xc4, 0x78, 0xaa, 0xbd, 0xb3, 0x56, 0x8b, 0xff, 0x37, 0x3c, 0xaa, 0x9e, 0x9e,
0xea, 0xe9, 0x99, 0x9c, 0xba, 0xcd, 0xa7, 0x9c, 0x91, 0x7f, 0xc2, 0xff, 0xa3, 0x53, 0xec, 0x8f, 0xc9, 0xa9, 0xdb, 0x7c, 0xca, 0x19, 0xf9, 0x27, 0xfc, 0x3f, 0x3a, 0xc5, 0xfe, 0xc8, 0xc9, 0xe5,
0x9c, 0x5c, 0x3e, 0x1e, 0x0c, 0x8e, 0xbb, 0xa4, 0xea, 0x0c, 0x3b, 0x55, 0xa7, 0xdf, 0x1f, 0xf8, 0xe3, 0xc1, 0xe0, 0xb8, 0x4b, 0xaa, 0xce, 0xb0, 0x53, 0x75, 0xfa, 0xfd, 0x81, 0xef, 0xf8, 0x9d,
0x8e, 0xdf, 0x19, 0xf4, 0x3d, 0x31, 0x8b, 0xbf, 0xc8, 0x40, 0xd9, 0x26, 0xde, 0x90, 0x52, 0xc8, 0x41, 0xdf, 0x13, 0xb3, 0xf8, 0xf3, 0x0c, 0x94, 0x6d, 0xe2, 0x0d, 0x29, 0x85, 0xbc, 0x47, 0x9c,
0x7b, 0xc4, 0x69, 0x13, 0x17, 0xdd, 0x01, 0x68, 0x75, 0x47, 0x9e, 0x4f, 0xdc, 0xc3, 0x4e, 0xbb, 0x36, 0x71, 0xd1, 0x1d, 0x80, 0x56, 0x77, 0xe4, 0xf9, 0xc4, 0x3d, 0xec, 0xb4, 0x2b, 0x99, 0xd5,
0x92, 0x59, 0xcd, 0x3c, 0xc9, 0xdb, 0x05, 0x49, 0xd9, 0x6a, 0xa3, 0xdb, 0x50, 0xe8, 0x91, 0xde, 0xcc, 0x93, 0xbc, 0x5d, 0x90, 0x94, 0xad, 0x36, 0xba, 0x0d, 0x85, 0x1e, 0xe9, 0x1d, 0x89, 0xd9,
0x91, 0x98, 0xcd, 0xf2, 0xd9, 0x59, 0x41, 0xa0, 0x93, 0x16, 0xcc, 0xba, 0xe4, 0xac, 0xe3, 0x51, 0x2c, 0x9f, 0x9d, 0x15, 0x04, 0x3a, 0x69, 0xc1, 0xac, 0x4b, 0xce, 0x3a, 0x1e, 0x45, 0xa8, 0xe4,
0x84, 0x4a, 0x8e, 0xce, 0xe5, 0xec, 0x60, 0xcc, 0x16, 0xba, 0xce, 0x0b, 0xff, 0x90, 0x8a, 0xe9, 0xe8, 0x5c, 0xce, 0x0e, 0xc6, 0x6c, 0xa1, 0xeb, 0xbc, 0xf0, 0x0f, 0xa9, 0x98, 0x5e, 0x25, 0x2f,
0x55, 0xf2, 0x62, 0x21, 0x23, 0x34, 0xe9, 0x18, 0xff, 0x3a, 0x07, 0x25, 0xdb, 0xe9, 0x1f, 0x13, 0x16, 0x32, 0x42, 0x93, 0x8e, 0xf1, 0x97, 0x39, 0x28, 0xd9, 0x4e, 0xff, 0x98, 0xd8, 0xe4, 0x93,
0x9b, 0x7c, 0x32, 0x22, 0x9e, 0x8f, 0xe6, 0x21, 0x77, 0x4a, 0x2e, 0x38, 0x7c, 0xc9, 0x66, 0x8f, 0x11, 0xf1, 0x7c, 0x34, 0x0f, 0xb9, 0x53, 0x72, 0xc1, 0xe1, 0x4b, 0x36, 0x7b, 0x14, 0xeb, 0x29,
0x62, 0x3d, 0xe5, 0x38, 0x24, 0x7d, 0x01, 0x5c, 0x62, 0xeb, 0x29, 0xa1, 0xd1, 0x6f, 0xa3, 0x45, 0xc7, 0x21, 0xe9, 0x0b, 0xe0, 0x12, 0x5b, 0x4f, 0x09, 0x8d, 0x7e, 0x1b, 0x2d, 0xc2, 0x54, 0xb7,
0x98, 0xea, 0x76, 0x7a, 0x1d, 0x5f, 0xa2, 0x8a, 0x41, 0x44, 0x9d, 0x7c, 0x4c, 0x9d, 0x4d, 0x00, 0xd3, 0xeb, 0xf8, 0x12, 0x55, 0x0c, 0x22, 0xea, 0xe4, 0x63, 0xea, 0x6c, 0x02, 0x78, 0x03, 0xd7,
0x6f, 0xe0, 0xfa, 0x87, 0x03, 0x97, 0x6e, 0xba, 0x32, 0x45, 0x67, 0xcb, 0xeb, 0x0f, 0xd6, 0xf4, 0x3f, 0x1c, 0xb8, 0x74, 0xd3, 0x95, 0x29, 0x3a, 0x5b, 0x5e, 0x7f, 0xb0, 0xa6, 0x1f, 0xc4, 0x9a,
0x83, 0x58, 0xd3, 0x15, 0x5a, 0xdb, 0xa7, 0xcc, 0x7b, 0x8c, 0xd7, 0x2e, 0x78, 0xea, 0x11, 0x7d, 0xae, 0xd0, 0xda, 0x3e, 0x65, 0xde, 0x63, 0xbc, 0x76, 0xc1, 0x53, 0x8f, 0xe8, 0x7b, 0x50, 0xe4,
0x07, 0x8a, 0x5c, 0x88, 0xef, 0xb8, 0xc7, 0xc4, 0xaf, 0x4c, 0x73, 0x29, 0x0f, 0x2f, 0x91, 0xd2, 0x42, 0x7c, 0xc7, 0x3d, 0x26, 0x7e, 0x65, 0x9a, 0x4b, 0x79, 0x78, 0x89, 0x94, 0x26, 0x67, 0xb6,
0xe4, 0xcc, 0x36, 0x87, 0x17, 0xcf, 0x08, 0x43, 0x89, 0xf2, 0x77, 0x9c, 0x6e, 0xe7, 0x53, 0xe7, 0x39, 0xbc, 0x78, 0x46, 0x18, 0x4a, 0x94, 0xbf, 0xe3, 0x74, 0x3b, 0x9f, 0x3a, 0x47, 0x5d, 0x52,
0xa8, 0x4b, 0x2a, 0x33, 0x54, 0xd0, 0xac, 0x1d, 0xa1, 0xb1, 0xfd, 0x53, 0x33, 0x78, 0x87, 0x83, 0x99, 0xa1, 0x82, 0x66, 0xed, 0x08, 0x8d, 0xed, 0x9f, 0x9a, 0xc1, 0x3b, 0x1c, 0xf4, 0xbb, 0x17,
0x7e, 0xf7, 0xa2, 0x32, 0xcb, 0x19, 0x66, 0x19, 0x61, 0x8f, 0x8e, 0xf1, 0x1a, 0x14, 0x02, 0x05, 0x95, 0x59, 0xce, 0x30, 0xcb, 0x08, 0x7b, 0x74, 0xcc, 0x0f, 0x6d, 0x30, 0xea, 0xfb, 0x62, 0xb6,
0xd1, 0x2c, 0xe4, 0x77, 0xf7, 0x76, 0x1b, 0xf3, 0xd7, 0x10, 0xc0, 0x74, 0x6d, 0x7f, 0xb3, 0xb1, 0xc0, 0x67, 0x0b, 0x9c, 0xc2, 0xa6, 0xf1, 0x1a, 0x14, 0x02, 0xfd, 0xd1, 0x2c, 0xe4, 0x77, 0xf7,
0x5b, 0x9f, 0xcf, 0xa0, 0x22, 0xcc, 0xd4, 0x1b, 0x62, 0x90, 0xc5, 0x1b, 0x00, 0xa1, 0x2a, 0x68, 0x76, 0x1b, 0xf3, 0xd7, 0x10, 0xc0, 0x74, 0x6d, 0x7f, 0xb3, 0xb1, 0x5b, 0x9f, 0xcf, 0xa0, 0x22,
0x06, 0x72, 0xdb, 0x8d, 0xef, 0x52, 0x7e, 0xca, 0x73, 0xd0, 0xb0, 0xf7, 0xb7, 0xf6, 0x76, 0xe9, 0xcc, 0xd4, 0x1b, 0x62, 0x90, 0xc5, 0x1b, 0x00, 0xa1, 0xa6, 0x68, 0x06, 0x72, 0xdb, 0x8d, 0xef,
0x02, 0xba, 0x78, 0xd3, 0x6e, 0xd4, 0x9a, 0x8d, 0xf9, 0x2c, 0xe3, 0xf8, 0x60, 0xaf, 0x3e, 0x9f, 0x53, 0x7e, 0xca, 0x73, 0xd0, 0xb0, 0xf7, 0xb7, 0xf6, 0x76, 0xe9, 0x02, 0xba, 0x78, 0xd3, 0x6e,
0x43, 0x05, 0x98, 0x3a, 0xa8, 0xed, 0x3c, 0x6f, 0xcc, 0xe7, 0xf1, 0x67, 0x30, 0x27, 0xf7, 0x26, 0xd4, 0x9a, 0x8d, 0xf9, 0x2c, 0xe3, 0xf8, 0x60, 0xaf, 0x3e, 0x9f, 0x43, 0x05, 0x98, 0x3a, 0xa8,
0xee, 0x0f, 0x7a, 0x07, 0xa6, 0x4f, 0xf8, 0x1d, 0xe2, 0xc7, 0x56, 0x5c, 0x5f, 0x8e, 0x19, 0x22, 0xed, 0x3c, 0x6f, 0xcc, 0xe7, 0xf1, 0x17, 0x19, 0x98, 0x93, 0x7b, 0x17, 0xf7, 0x0b, 0xbd, 0x03,
0x72, 0xcf, 0x6c, 0xc9, 0x4b, 0xf7, 0x9e, 0x3b, 0x3d, 0xf3, 0xe8, 0x89, 0xe6, 0xe8, 0x92, 0xf9, 0xd3, 0x27, 0xfc, 0x8e, 0xf1, 0x63, 0x2d, 0xae, 0x2f, 0xc7, 0x0c, 0x15, 0xb9, 0x87, 0xb6, 0xe4,
0x35, 0x71, 0xb9, 0xd7, 0xb6, 0xc9, 0xc5, 0x81, 0xd3, 0x1d, 0x11, 0x9b, 0x4d, 0x22, 0x04, 0xf9, 0xa5, 0xb6, 0xc9, 0x9d, 0x9e, 0x79, 0xf4, 0xc4, 0x73, 0x74, 0xc9, 0xfc, 0x9a, 0xb8, 0xfc, 0x6b,
0xde, 0xc0, 0x25, 0xfc, 0x74, 0x67, 0x6d, 0xfe, 0x8c, 0xdf, 0x07, 0x78, 0x36, 0xf2, 0x93, 0xef, 0xdb, 0xe4, 0xe2, 0xc0, 0xe9, 0x8e, 0x88, 0xcd, 0x26, 0x11, 0x82, 0x7c, 0x6f, 0xe0, 0x12, 0x7e,
0x0b, 0xbd, 0x12, 0x67, 0x4c, 0x82, 0xbc, 0x2b, 0x62, 0xc0, 0x2f, 0x0a, 0x71, 0x3c, 0x12, 0x5c, 0xfa, 0xb3, 0x36, 0x7f, 0x66, 0x57, 0x82, 0x1b, 0x40, 0x9e, 0xbc, 0x18, 0xe0, 0xf7, 0x01, 0x9e,
0x14, 0x36, 0xc0, 0x9b, 0x50, 0xe4, 0xb2, 0xd2, 0x6c, 0x84, 0x0a, 0x41, 0x75, 0xd2, 0x25, 0x3e, 0x8d, 0xfc, 0xe4, 0x5b, 0x46, 0x57, 0x9d, 0x31, 0xb9, 0xf2, 0x86, 0x89, 0x01, 0xbf, 0x5e, 0xc4,
0x49, 0x71, 0x91, 0x31, 0x81, 0x85, 0x88, 0x90, 0x54, 0xa6, 0xad, 0xc0, 0x4c, 0x9b, 0x0b, 0x13, 0xf1, 0x48, 0x70, 0xbd, 0xd8, 0x00, 0x6f, 0x42, 0x91, 0xcb, 0x4a, 0xb3, 0x3d, 0x2a, 0x04, 0xd5,
0x38, 0x39, 0x5b, 0x0d, 0xf1, 0x3f, 0x32, 0x50, 0x90, 0x1a, 0xee, 0x0d, 0x51, 0x0d, 0xe6, 0x5c, 0x49, 0x97, 0xf8, 0x24, 0xc5, 0xf5, 0xc7, 0x04, 0x16, 0x22, 0x42, 0x52, 0x19, 0xbc, 0x02, 0x33,
0x31, 0x38, 0xe4, 0x8a, 0x48, 0x10, 0x2b, 0xf9, 0x22, 0xbf, 0x77, 0xcd, 0x2e, 0xc9, 0x25, 0x9c, 0x6d, 0x2e, 0x4c, 0xe0, 0xe4, 0x6c, 0x35, 0xc4, 0xff, 0xcc, 0x40, 0x41, 0x6a, 0xb8, 0x37, 0x44,
0x8c, 0xbe, 0x05, 0x45, 0x25, 0x62, 0x38, 0xf2, 0x39, 0x5c, 0x71, 0xbd, 0x12, 0x15, 0x10, 0x1e, 0x35, 0x98, 0x73, 0xc5, 0xe0, 0x90, 0x2b, 0x22, 0x41, 0xac, 0xe4, 0xeb, 0xff, 0xde, 0x35, 0xbb,
0x17, 0x5d, 0x0e, 0x92, 0x9d, 0x12, 0x51, 0x13, 0x16, 0xd5, 0x62, 0xa1, 0xa0, 0x54, 0x23, 0xc7, 0x24, 0x97, 0x70, 0x32, 0xfa, 0x0e, 0x14, 0x95, 0x88, 0xe1, 0xc8, 0xe7, 0x70, 0xc5, 0xf5, 0x4a,
0xa5, 0xac, 0x46, 0xa5, 0x8c, 0xdb, 0x98, 0x4a, 0x43, 0x72, 0xbd, 0x36, 0xb9, 0x51, 0x80, 0x19, 0x54, 0x40, 0x78, 0x5c, 0x74, 0x39, 0x48, 0x76, 0x4a, 0x44, 0x4d, 0x58, 0x54, 0x8b, 0x85, 0x82,
0x49, 0xc5, 0xff, 0xcc, 0x00, 0x28, 0x1b, 0xd1, 0xfd, 0xd6, 0xa1, 0xec, 0xca, 0x51, 0x64, 0xc3, 0x52, 0x8d, 0x1c, 0x97, 0xb2, 0x1a, 0x95, 0x32, 0x6e, 0x63, 0x2a, 0x0d, 0xc9, 0xf5, 0xda, 0xe4,
0xb7, 0x8d, 0x1b, 0x96, 0xa6, 0xbd, 0x66, 0xcf, 0xa9, 0x45, 0x62, 0xcb, 0xef, 0x42, 0x29, 0x90, 0x46, 0x01, 0x66, 0x24, 0x15, 0xff, 0x2b, 0x03, 0xa0, 0x6c, 0x44, 0xf7, 0x5b, 0x87, 0xb2, 0x2b,
0x12, 0xee, 0x79, 0xc9, 0xb0, 0xe7, 0x40, 0x42, 0x51, 0x2d, 0x60, 0xbb, 0xfe, 0x08, 0x6e, 0x06, 0x47, 0x91, 0x0d, 0xdf, 0x36, 0x6e, 0x58, 0x9a, 0xf6, 0x9a, 0x3d, 0xa7, 0x16, 0x89, 0x2d, 0xbf,
0xeb, 0x0d, 0xdb, 0xbe, 0x37, 0x61, 0xdb, 0x81, 0xc0, 0x05, 0x25, 0x41, 0xdf, 0x38, 0xb0, 0xb0, 0x0b, 0xa5, 0x40, 0x4a, 0xb8, 0xe7, 0x25, 0xc3, 0x9e, 0x03, 0x09, 0x45, 0xb5, 0x80, 0xed, 0xfa,
0x27, 0xc8, 0xf8, 0x17, 0x39, 0x98, 0xd9, 0x1c, 0xf4, 0x86, 0x8e, 0xcb, 0xce, 0x68, 0x9a, 0xd2, 0x23, 0xb8, 0x19, 0xac, 0x37, 0x6c, 0xfb, 0xde, 0x84, 0x6d, 0x07, 0x02, 0x17, 0x94, 0x04, 0x7d,
0x47, 0x5d, 0x9f, 0x6f, 0xb7, 0xbc, 0x7e, 0x3f, 0x8a, 0x20, 0xd9, 0xd4, 0x5f, 0x9b, 0xb3, 0xda, 0xe3, 0xc0, 0x82, 0xa5, 0x20, 0xe3, 0x5f, 0xe7, 0x60, 0x66, 0x73, 0xd0, 0x1b, 0x3a, 0x2e, 0x3b,
0x72, 0x09, 0x5b, 0x2c, 0xa3, 0x5c, 0xf6, 0x0a, 0x8b, 0x65, 0x8c, 0x93, 0x4b, 0x94, 0x13, 0xe4, 0xa3, 0x69, 0x4a, 0x1f, 0x75, 0x7d, 0xbe, 0xdd, 0xf2, 0xfa, 0xfd, 0x28, 0x82, 0x64, 0x53, 0x7f,
0x42, 0x27, 0xb0, 0x60, 0x86, 0x2e, 0x0c, 0x23, 0x33, 0xdd, 0x8b, 0x22, 0xa0, 0x57, 0xe1, 0x7a, 0x6d, 0xce, 0x6a, 0xcb, 0x25, 0x6c, 0xb1, 0x8c, 0x8d, 0xd9, 0x2b, 0x2c, 0x96, 0x91, 0x51, 0x2e,
0xcb, 0x25, 0x0e, 0xb3, 0x87, 0x8a, 0xde, 0x53, 0x92, 0xa7, 0x2c, 0x26, 0x6c, 0x15, 0xc5, 0xef, 0x51, 0x4e, 0x90, 0x0b, 0x9d, 0xc0, 0x82, 0x19, 0xba, 0x30, 0x8c, 0xe7, 0x74, 0x2f, 0x8a, 0x80,
0x43, 0xa9, 0x37, 0x68, 0x87, 0x7c, 0xd3, 0x92, 0xaf, 0x48, 0xa9, 0x01, 0xd3, 0x2d, 0x15, 0x09, 0x5e, 0x85, 0xeb, 0x2d, 0x97, 0x38, 0xcc, 0x1e, 0x2a, 0xe6, 0x4f, 0x49, 0x9e, 0xb2, 0x98, 0xb0,
0x58, 0x58, 0x2d, 0xd1, 0x59, 0x31, 0xc4, 0x6f, 0xc1, 0x5c, 0x64, 0xaf, 0x2c, 0xb8, 0x35, 0x3e, 0x55, 0xec, 0xbf, 0x0f, 0xa5, 0xde, 0xa0, 0x1d, 0xf2, 0x4d, 0x4b, 0xbe, 0x22, 0xa5, 0x06, 0x4c,
0x7c, 0x5e, 0xdb, 0x11, 0x91, 0xf0, 0x29, 0x0f, 0x7e, 0x36, 0x8d, 0x84, 0x34, 0xa0, 0xee, 0x34, 0xb7, 0x54, 0x24, 0x60, 0xc1, 0xb8, 0x44, 0x67, 0xc5, 0x10, 0xbf, 0x05, 0x73, 0x91, 0xbd, 0xb2,
0xf6, 0xf7, 0x69, 0xdc, 0xfc, 0x76, 0xb0, 0x44, 0x86, 0x4e, 0x2d, 0x62, 0x5e, 0xd3, 0x22, 0x66, 0x98, 0xd7, 0xf8, 0xf0, 0x79, 0x6d, 0x47, 0x04, 0xc8, 0xa7, 0x3c, 0x26, 0xda, 0x34, 0x40, 0xd2,
0x46, 0x45, 0xcc, 0x6c, 0x18, 0x31, 0x73, 0x1b, 0x65, 0x28, 0x09, 0x83, 0x1c, 0x8e, 0xfa, 0x54, 0x38, 0xbb, 0xd3, 0xd8, 0xdf, 0xa7, 0xe1, 0xf4, 0xbb, 0xc1, 0x12, 0x19, 0x51, 0xb5, 0x40, 0x7a,
0x31, 0xfc, 0x2b, 0x7a, 0x2d, 0x9b, 0xe7, 0x7d, 0x15, 0x2a, 0xaa, 0x30, 0xd3, 0x12, 0xc2, 0xe9, 0x4d, 0x0b, 0xa4, 0x19, 0x15, 0x48, 0xb3, 0x61, 0x20, 0xcd, 0x6d, 0x94, 0xa1, 0x24, 0x0c, 0x72,
0x01, 0xb1, 0x68, 0x78, 0xd3, 0x68, 0x63, 0x5b, 0x71, 0xa1, 0xb7, 0x60, 0xc6, 0x1b, 0xb5, 0x5a, 0x38, 0xea, 0x53, 0xc5, 0xf0, 0x6f, 0xe9, 0xb5, 0x6c, 0x9e, 0xf7, 0x55, 0xa8, 0xa8, 0xc2, 0x4c,
0xc4, 0x53, 0xe1, 0xf3, 0x95, 0x78, 0x58, 0x90, 0x1e, 0x6e, 0x2b, 0x3e, 0xb6, 0xe4, 0x85, 0xd3, 0x4b, 0x08, 0xa7, 0x07, 0xc4, 0x62, 0xe4, 0x4d, 0xa3, 0x8d, 0x6d, 0xc5, 0x85, 0xde, 0x82, 0x19,
0xe9, 0x8e, 0x78, 0x30, 0x9d, 0xbc, 0x44, 0xf2, 0xe1, 0x9f, 0x67, 0xa0, 0xc8, 0xb5, 0x4c, 0x15, 0x6f, 0xd4, 0x6a, 0x11, 0x4f, 0x05, 0xd5, 0x57, 0xe2, 0x61, 0x41, 0x7a, 0xb8, 0xad, 0xf8, 0xd8,
0x8b, 0x96, 0xa1, 0xc0, 0x75, 0x20, 0x6d, 0x19, 0x8d, 0x66, 0xed, 0x90, 0x80, 0xbe, 0x41, 0x63, 0x92, 0x17, 0x4e, 0xa7, 0x3b, 0xe2, 0x21, 0x76, 0xf2, 0x12, 0xc9, 0x87, 0x7f, 0x95, 0x81, 0x22,
0xa2, 0x5c, 0xe7, 0x49, 0xc5, 0x2a, 0x66, 0xb1, 0x54, 0xb3, 0x90, 0x15, 0x6f, 0xc3, 0x0d, 0x6e, 0xd7, 0x32, 0x55, 0x2c, 0x5a, 0x86, 0x02, 0xd7, 0x81, 0xb4, 0x65, 0x34, 0xa2, 0xaf, 0xb5, 0x80,
0x95, 0x16, 0x4b, 0x6a, 0x94, 0x1d, 0xf5, 0xd7, 0x7e, 0x26, 0xf6, 0xda, 0xa7, 0x73, 0xc3, 0x93, 0x80, 0xbe, 0x45, 0x63, 0xa2, 0x5c, 0xe7, 0x49, 0xc5, 0x2a, 0x66, 0xb1, 0x54, 0xb3, 0x90, 0x15,
0x0b, 0xaf, 0xd3, 0x72, 0xba, 0x52, 0x8b, 0x60, 0x4c, 0xdf, 0x28, 0x48, 0x17, 0x96, 0xea, 0x65, 0x6f, 0xc3, 0x0d, 0x6e, 0x95, 0x16, 0x4b, 0x85, 0x94, 0x1d, 0xf5, 0x64, 0x21, 0x13, 0x4b, 0x16,
0x30, 0x07, 0xc5, 0xf7, 0x1c, 0xef, 0x44, 0xaa, 0x84, 0x3f, 0x86, 0x92, 0x18, 0xa6, 0xb2, 0x21, 0xe8, 0xdc, 0xf0, 0xe4, 0xc2, 0xeb, 0xb4, 0x9c, 0xae, 0xd4, 0x22, 0x18, 0xd3, 0x37, 0x0a, 0xd2,
0x7d, 0x0d, 0x9e, 0x50, 0x29, 0x5c, 0xf1, 0x39, 0x9b, 0x3f, 0xe3, 0x1b, 0x70, 0x7d, 0xbf, 0xef, 0x85, 0xa5, 0x7a, 0x19, 0xcc, 0x41, 0xf1, 0x3d, 0xc7, 0x3b, 0x91, 0x2a, 0xe1, 0x8f, 0xa1, 0x24,
0x0c, 0xbd, 0x93, 0x81, 0x0a, 0xae, 0x2c, 0xa9, 0x9b, 0x0f, 0x69, 0xa9, 0x10, 0x1f, 0xc3, 0x75, 0x86, 0xa9, 0x6c, 0x48, 0x5f, 0x8e, 0x27, 0x54, 0x0a, 0x57, 0x7c, 0xce, 0xe6, 0xcf, 0xf8, 0x06,
0x97, 0xf4, 0x9c, 0x4e, 0xbf, 0xd3, 0x3f, 0x3e, 0x3c, 0xba, 0xf0, 0x89, 0x27, 0x73, 0xbe, 0x72, 0x5c, 0xdf, 0xef, 0x3b, 0x43, 0xef, 0x64, 0xa0, 0x82, 0x2b, 0x4b, 0x05, 0xe7, 0x43, 0x5a, 0x2a,
0x40, 0xde, 0x60, 0x54, 0xa6, 0xda, 0x51, 0x77, 0x70, 0x24, 0x5d, 0x9c, 0x3f, 0xe3, 0xdf, 0x64, 0xc4, 0xc7, 0x70, 0xdd, 0x25, 0x3d, 0xa7, 0xd3, 0xef, 0xf4, 0x8f, 0x0f, 0x8f, 0x2e, 0x7c, 0xe2,
0xa0, 0xf4, 0x91, 0xe3, 0xb7, 0x94, 0x15, 0xd0, 0x16, 0x94, 0x03, 0xc7, 0xe6, 0x14, 0xa9, 0x4b, 0xc9, 0x4c, 0xb1, 0x1c, 0x90, 0x37, 0x18, 0x95, 0xa9, 0x76, 0xd4, 0x1d, 0x1c, 0x49, 0x17, 0xe7,
0x2c, 0xc2, 0xf3, 0x35, 0x9b, 0xd2, 0xd1, 0x55, 0x84, 0x9f, 0x6b, 0xe9, 0x04, 0x2e, 0xca, 0xe9, 0xcf, 0xf8, 0x77, 0x19, 0x28, 0x7d, 0xe4, 0xf8, 0x2d, 0x65, 0x05, 0xb4, 0x05, 0xe5, 0xc0, 0xb1,
0xb7, 0x48, 0x37, 0x10, 0x95, 0x4d, 0x16, 0xc5, 0x19, 0x75, 0x51, 0x3a, 0x61, 0xe3, 0x7a, 0xf8, 0x39, 0x45, 0xea, 0x12, 0x8b, 0xf0, 0x7c, 0xcd, 0xa6, 0x74, 0x74, 0x15, 0xe1, 0xe7, 0x5a, 0x3a,
0xf6, 0x13, 0x6e, 0xf9, 0x65, 0x06, 0xd0, 0xb8, 0x0e, 0x5f, 0x35, 0x25, 0x7d, 0x08, 0x65, 0x8f, 0x81, 0x8b, 0x72, 0xfa, 0x2d, 0xd2, 0x0d, 0x44, 0x65, 0x93, 0x45, 0x71, 0x46, 0x5d, 0x94, 0x4e,
0x7a, 0xbb, 0x7f, 0x18, 0xcb, 0x88, 0xe7, 0x38, 0x35, 0x08, 0x4e, 0xd4, 0xc2, 0x34, 0x15, 0x3f, 0xd8, 0xb8, 0x1e, 0xbe, 0xfd, 0x84, 0x5b, 0xd2, 0x7c, 0x07, 0x8d, 0xeb, 0xf0, 0x55, 0x13, 0xd9,
0xa6, 0x57, 0xda, 0x3b, 0xa4, 0xd9, 0x79, 0xe7, 0xc5, 0x05, 0x0f, 0x88, 0xb3, 0x76, 0x59, 0x91, 0x87, 0x50, 0xf6, 0xa8, 0xb7, 0xfb, 0x87, 0xb1, 0x3c, 0x7a, 0x8e, 0x53, 0x83, 0xe0, 0x44, 0x2d,
0x77, 0x39, 0x15, 0x57, 0x95, 0x52, 0xba, 0xf2, 0x68, 0x09, 0x66, 0x5f, 0x32, 0xaa, 0xca, 0xd5, 0x4c, 0x13, 0xf8, 0x63, 0x7a, 0xa5, 0xbd, 0x43, 0x9a, 0xd3, 0x77, 0x5e, 0x5c, 0xf0, 0x80, 0x38,
0xe9, 0x3b, 0x9e, 0x8f, 0xb7, 0xda, 0xf8, 0xef, 0x19, 0x98, 0x93, 0xe6, 0x4f, 0x75, 0x07, 0x74, 0x6b, 0x97, 0x15, 0x79, 0x97, 0x53, 0x71, 0x55, 0x29, 0xa5, 0x2b, 0x8f, 0x96, 0x60, 0xf6, 0x25,
0x88, 0x6c, 0x04, 0x82, 0x25, 0x18, 0xe2, 0x58, 0xda, 0x32, 0x35, 0x53, 0x43, 0xe6, 0x67, 0xc2, 0xa3, 0xaa, 0x0c, 0x9f, 0xbe, 0xe3, 0xf9, 0x78, 0xab, 0x8d, 0xff, 0x41, 0xd3, 0x36, 0x69, 0xfe,
0xca, 0x74, 0x4a, 0xec, 0x27, 0x18, 0xd3, 0xf8, 0x3e, 0xdf, 0x12, 0x7e, 0x16, 0x0b, 0xf0, 0xf6, 0x54, 0x77, 0x40, 0x87, 0xc8, 0x46, 0x20, 0x58, 0x82, 0x21, 0x8e, 0xa5, 0x2d, 0x13, 0x36, 0x35,
0x75, 0x49, 0x0f, 0xac, 0xf3, 0x10, 0xa6, 0xc9, 0x19, 0xe9, 0xfb, 0x5e, 0xa5, 0xc8, 0x83, 0xc2, 0x64, 0x7e, 0x26, 0xac, 0x4c, 0xa7, 0xc4, 0x7e, 0x82, 0x31, 0x8d, 0xef, 0xf3, 0x2d, 0xe1, 0x67,
0x9c, 0xca, 0x0f, 0x1b, 0x8c, 0x6a, 0xcb, 0x49, 0xfc, 0xff, 0x70, 0x63, 0x87, 0x25, 0x72, 0x4f, 0xb1, 0x00, 0x6f, 0x5f, 0x97, 0xf4, 0xc0, 0x3a, 0x0f, 0x61, 0x9a, 0x9c, 0x91, 0xbe, 0xef, 0x55,
0xa9, 0xf5, 0xf5, 0x94, 0xb0, 0xd9, 0xdc, 0x91, 0x56, 0xc9, 0xf9, 0xcd, 0x1d, 0x54, 0x86, 0xec, 0x8a, 0x3c, 0x28, 0xcc, 0xa9, 0xac, 0xb1, 0xc1, 0xa8, 0xb6, 0x9c, 0xc4, 0xdf, 0x84, 0x1b, 0x3b,
0x56, 0x5d, 0xee, 0x21, 0xdb, 0xa9, 0xe3, 0xcf, 0xe9, 0x41, 0xeb, 0xeb, 0x52, 0x99, 0x29, 0x26, 0x2c, 0x91, 0x7b, 0x4a, 0xad, 0xaf, 0xa7, 0x84, 0xcd, 0xe6, 0x8e, 0xb4, 0x4a, 0xce, 0x6f, 0xee,
0x5c, 0xc1, 0xe7, 0x42, 0x78, 0x9a, 0x7b, 0x12, 0xd7, 0x1d, 0xb8, 0xdc, 0x20, 0x05, 0x5b, 0x0c, 0xa0, 0x32, 0x64, 0xb7, 0xea, 0x72, 0x0f, 0xd9, 0x4e, 0x1d, 0x7f, 0x46, 0x0f, 0x5a, 0x5f, 0x97,
0xf0, 0x03, 0xa9, 0x03, 0xdd, 0xf3, 0xe0, 0x34, 0xb8, 0x6c, 0x42, 0x5a, 0x26, 0x50, 0x75, 0x1b, 0xca, 0x4c, 0x31, 0xe1, 0x0a, 0x3e, 0x17, 0xc2, 0xd3, 0xdc, 0x93, 0xb8, 0xee, 0xc0, 0xe5, 0x06,
0x16, 0x22, 0x5c, 0xa9, 0x82, 0xd3, 0x63, 0xb8, 0xc9, 0x85, 0x6d, 0x13, 0x32, 0xac, 0x75, 0x3b, 0x29, 0xd8, 0x62, 0x80, 0x1f, 0x48, 0x1d, 0xe8, 0x9e, 0x07, 0xa7, 0xc1, 0x65, 0x13, 0xd2, 0x32,
0x67, 0x89, 0xa8, 0x43, 0xb8, 0x15, 0x67, 0xfc, 0x7a, 0x6d, 0x84, 0x4f, 0x60, 0xfa, 0x03, 0x5e, 0x81, 0xaa, 0xdb, 0xb0, 0x10, 0xe1, 0x4a, 0x15, 0x9c, 0x1e, 0xc3, 0x4d, 0x2e, 0x6c, 0x9b, 0x90,
0x4d, 0x6a, 0xba, 0xe4, 0x39, 0x2f, 0x8d, 0x30, 0x7d, 0xa7, 0x27, 0xd2, 0xf9, 0x82, 0xcd, 0x9f, 0x61, 0xad, 0xdb, 0x39, 0x4b, 0x44, 0x1d, 0xc2, 0xad, 0x38, 0xe3, 0xd7, 0x6b, 0x23, 0x7c, 0x02,
0x79, 0x34, 0x27, 0xc4, 0x7d, 0x6e, 0xef, 0x88, 0xb7, 0x46, 0xc1, 0x0e, 0xc6, 0x68, 0x85, 0xd5, 0xd3, 0x1f, 0xf0, 0x1a, 0x54, 0xd3, 0x25, 0xcf, 0x79, 0x69, 0x84, 0xe9, 0x3b, 0x3d, 0x91, 0xce,
0xb1, 0x1d, 0x7a, 0x3d, 0xf8, 0x6c, 0x9e, 0xcf, 0x6a, 0x14, 0x5a, 0x32, 0xcd, 0x0b, 0xa4, 0x5a, 0x17, 0x6c, 0xfe, 0xcc, 0xa3, 0x39, 0x21, 0xee, 0x73, 0x7b, 0x47, 0xbc, 0x35, 0x0a, 0x76, 0x30,
0xbb, 0xad, 0xbd, 0x39, 0x02, 0x79, 0x99, 0xa8, 0x3c, 0xfc, 0x12, 0x6e, 0x68, 0xfc, 0xa9, 0xcc, 0x46, 0x2b, 0xac, 0xfa, 0xed, 0xd0, 0xeb, 0xc1, 0x67, 0xf3, 0x7c, 0x56, 0xa3, 0xd0, 0x4a, 0x6a,
0xf0, 0x06, 0x4c, 0x8b, 0x92, 0x59, 0x06, 0xad, 0xc5, 0xe8, 0x2a, 0x01, 0x63, 0x4b, 0x1e, 0xfc, 0x5e, 0x20, 0xd5, 0xda, 0x6d, 0xed, 0xcd, 0x11, 0xc8, 0xcb, 0x44, 0xe5, 0xe1, 0x97, 0x70, 0x43,
0x10, 0x16, 0x24, 0x85, 0xf4, 0x06, 0xa6, 0xb3, 0xe2, 0xf6, 0xc1, 0x3b, 0xb0, 0x18, 0x65, 0x4b, 0xe3, 0x4f, 0x65, 0x86, 0x37, 0x60, 0x5a, 0x14, 0xda, 0x32, 0x68, 0x2d, 0x46, 0x57, 0x09, 0x18,
0x75, 0x45, 0x6a, 0x0a, 0xf4, 0xf9, 0xb0, 0xad, 0xc5, 0xc0, 0xf8, 0xa1, 0xe8, 0x06, 0xcb, 0xc6, 0x5b, 0xf2, 0xe0, 0x87, 0xb0, 0x20, 0x29, 0xa4, 0x37, 0x30, 0x9d, 0x15, 0xb7, 0x0f, 0xde, 0x81,
0x0c, 0x16, 0x28, 0xa4, 0x44, 0xa4, 0x52, 0x68, 0x41, 0x99, 0x7f, 0xa7, 0xe3, 0x05, 0x6f, 0xba, 0xc5, 0x28, 0x5b, 0xaa, 0x2b, 0x52, 0x53, 0xa0, 0xcf, 0x87, 0x6d, 0x2d, 0x06, 0xc6, 0x0f, 0x45,
0x4f, 0x01, 0xe9, 0xc4, 0x54, 0x87, 0xb2, 0x06, 0x33, 0xc2, 0xe0, 0x2a, 0x99, 0x32, 0x9f, 0x8a, 0x37, 0x58, 0x36, 0x66, 0xb0, 0x40, 0x21, 0x25, 0x22, 0x95, 0x42, 0x0b, 0xca, 0xfc, 0x3b, 0x1d,
0x62, 0x62, 0x0a, 0xd5, 0xc9, 0x0b, 0xd7, 0x39, 0xee, 0x91, 0x20, 0xe6, 0xb0, 0x14, 0x42, 0x27, 0x2f, 0x78, 0xd3, 0x7d, 0x0a, 0x48, 0x27, 0xa6, 0x3a, 0x94, 0x35, 0x98, 0x11, 0x06, 0x57, 0xc9,
0xa6, 0xda, 0xf1, 0x1f, 0xe8, 0xeb, 0xb3, 0xd6, 0x75, 0xdc, 0x9e, 0x32, 0xfe, 0xbb, 0x30, 0x2d, 0x94, 0xf9, 0x54, 0x14, 0x13, 0x53, 0xa8, 0x4e, 0x5e, 0xb8, 0xce, 0x71, 0x8f, 0x04, 0x31, 0x87,
0x72, 0x13, 0x99, 0xbf, 0x3f, 0x8a, 0x8a, 0xd1, 0x79, 0xc5, 0xa0, 0x26, 0x32, 0x19, 0xb9, 0x8a, 0xa5, 0x10, 0x3a, 0x31, 0xd5, 0x8e, 0xff, 0x44, 0x5f, 0x9f, 0xb5, 0xae, 0xe3, 0xf6, 0x94, 0xf1,
0x1d, 0x96, 0xec, 0xd4, 0xd4, 0x63, 0x9d, 0x9b, 0x3a, 0x7a, 0x13, 0xa6, 0x1c, 0xb6, 0x84, 0xfb, 0xdf, 0x85, 0x69, 0x91, 0x9b, 0xc8, 0xfc, 0xfd, 0x51, 0x54, 0x8c, 0xce, 0x2b, 0x06, 0x35, 0x91,
0x62, 0x39, 0x9e, 0x15, 0x72, 0x69, 0xcd, 0x8b, 0x21, 0xb1, 0x05, 0x17, 0x7e, 0x07, 0x8a, 0x1a, 0xc9, 0xc8, 0x55, 0xec, 0xb0, 0x64, 0x7f, 0xa7, 0x1e, 0xeb, 0xf7, 0xd4, 0xd1, 0x9b, 0x30, 0xe5,
0x02, 0x4b, 0x76, 0x9f, 0x36, 0x9a, 0x34, 0x03, 0x2e, 0xc1, 0x6c, 0x6d, 0xb3, 0xb9, 0x75, 0x20, 0xb0, 0x25, 0xdc, 0x17, 0xcb, 0xf1, 0xac, 0x90, 0x4b, 0x6b, 0x5e, 0x0c, 0x89, 0x2d, 0xb8, 0xf0,
0x72, 0xe0, 0x32, 0x40, 0xbd, 0x11, 0x8c, 0xb3, 0x34, 0x0b, 0x12, 0xab, 0xa4, 0x87, 0xeb, 0xfa, 0x3b, 0x50, 0xd4, 0x10, 0x58, 0xb2, 0xfb, 0xb4, 0xd1, 0xa4, 0x19, 0x70, 0x09, 0x66, 0x6b, 0x9b,
0x64, 0x92, 0xf4, 0xc9, 0x5e, 0x49, 0x9f, 0x73, 0x98, 0x93, 0xdb, 0x4f, 0x75, 0x07, 0xde, 0xa2, 0xcd, 0xad, 0x03, 0x91, 0x03, 0x97, 0x01, 0xea, 0x8d, 0x60, 0x9c, 0xa5, 0x59, 0x90, 0x58, 0x25,
0x16, 0x66, 0x62, 0xd4, 0x15, 0x58, 0x32, 0xc0, 0x2a, 0xef, 0x14, 0x8c, 0x98, 0x66, 0x0f, 0xfb, 0x3d, 0x5c, 0xd7, 0x27, 0x93, 0xa4, 0x4f, 0xf6, 0x4a, 0xfa, 0x9c, 0xc3, 0x9c, 0xdc, 0x7e, 0xaa,
0xbe, 0xe3, 0x8f, 0x3c, 0x75, 0x05, 0x7e, 0x9f, 0x81, 0xb2, 0xa2, 0xa4, 0xad, 0xde, 0x55, 0x89, 0x3b, 0xf0, 0x16, 0xb5, 0x30, 0x13, 0xa3, 0xae, 0xc0, 0x92, 0x01, 0x56, 0x79, 0xa7, 0x60, 0xc4,
0x24, 0x62, 0x5e, 0x50, 0x20, 0xdd, 0x82, 0xe9, 0xf6, 0xd1, 0x7e, 0xe7, 0x53, 0xd5, 0xc5, 0x90, 0x34, 0x7b, 0xd8, 0xf7, 0x1d, 0x7f, 0xe4, 0xa9, 0x2b, 0xf0, 0xc7, 0x0c, 0x94, 0x15, 0x25, 0x6d,
0x23, 0x46, 0xef, 0x0a, 0x1c, 0xd1, 0x5f, 0x93, 0x23, 0x96, 0x7b, 0xb3, 0x4e, 0xdb, 0x56, 0xbf, 0xf5, 0xae, 0x4a, 0x24, 0x11, 0xf3, 0x82, 0x02, 0xe9, 0x16, 0x4c, 0xb7, 0x8f, 0xf6, 0x3b, 0x9f,
0x4d, 0xce, 0xf9, 0x9b, 0x36, 0x6f, 0x87, 0x04, 0x9e, 0x2e, 0xcb, 0x3e, 0x1c, 0xaf, 0x9f, 0xf4, 0xaa, 0x2e, 0x86, 0x1c, 0x31, 0x7a, 0x57, 0xe0, 0x88, 0xae, 0x9c, 0x1c, 0xb1, 0xdc, 0x9b, 0xf5,
0xbe, 0x1c, 0xbd, 0xe4, 0xb5, 0x91, 0x7f, 0xd2, 0xe8, 0xb3, 0x16, 0x94, 0xda, 0xe1, 0x22, 0x20, 0xe7, 0xb6, 0xfa, 0x6d, 0x72, 0xce, 0xdf, 0xb4, 0x79, 0x3b, 0x24, 0xf0, 0x74, 0x59, 0x76, 0xef,
0x46, 0xac, 0x77, 0x3c, 0x9d, 0xda, 0x80, 0x05, 0x46, 0xa5, 0xf7, 0x9e, 0x26, 0xd3, 0x61, 0xc4, 0x78, 0xfd, 0xa4, 0x77, 0xf3, 0xe8, 0x25, 0xaf, 0x8d, 0xfc, 0x93, 0x46, 0x9f, 0x35, 0xae, 0xd4,
0x50, 0x61, 0x3b, 0x13, 0x0b, 0xdb, 0x8e, 0xe7, 0xbd, 0x1c, 0xb8, 0x6d, 0xb9, 0xb5, 0x60, 0x8c, 0x0e, 0x17, 0x01, 0x31, 0x62, 0xbd, 0xe3, 0xe9, 0xd4, 0x06, 0x2c, 0x30, 0x2a, 0xbd, 0xf7, 0x34,
0xeb, 0x42, 0xf8, 0x73, 0x2f, 0x12, 0x98, 0xbf, 0xaa, 0x94, 0x27, 0xa1, 0x94, 0xa7, 0xc4, 0x9f, 0x99, 0x0e, 0x23, 0x86, 0x0a, 0xdb, 0x99, 0x58, 0xd8, 0x76, 0x3c, 0xef, 0xe5, 0xc0, 0x6d, 0xcb,
0x20, 0x05, 0xbf, 0x0e, 0x37, 0x15, 0xa7, 0xac, 0xa1, 0x27, 0x30, 0xef, 0xc1, 0x1d, 0xc5, 0xbc, 0xad, 0x05, 0x63, 0x5c, 0x17, 0xc2, 0x9f, 0x7b, 0x91, 0xc0, 0xfc, 0x55, 0xa5, 0x3c, 0x09, 0xa5,
0x79, 0xc2, 0x12, 0xbd, 0x67, 0x12, 0xf0, 0xbf, 0xd5, 0x73, 0x03, 0x2a, 0x81, 0x9e, 0x3c, 0x07, 0x3c, 0x25, 0xfe, 0x04, 0x29, 0xf8, 0x75, 0xb8, 0xa9, 0x38, 0x65, 0x0d, 0x3d, 0x81, 0x79, 0x0f,
0x19, 0x74, 0x75, 0x05, 0x46, 0x9e, 0xbc, 0x33, 0x54, 0x16, 0x7b, 0x66, 0x34, 0x97, 0xb2, 0xa8, 0xee, 0x28, 0xe6, 0xcd, 0x13, 0x96, 0xe8, 0x3d, 0x93, 0x80, 0xff, 0xab, 0x9e, 0x1b, 0x50, 0x09,
0x97, 0x20, 0x7b, 0xc6, 0x9b, 0xb0, 0xa4, 0x64, 0xc8, 0xec, 0x20, 0x2a, 0x64, 0x4c, 0x21, 0x93, 0xf4, 0xe4, 0x39, 0xc8, 0xa0, 0xab, 0x2b, 0x30, 0xf2, 0xe4, 0x9d, 0xa1, 0xb2, 0xd8, 0x33, 0xa3,
0x10, 0x69, 0x30, 0xb6, 0x74, 0xb2, 0xd9, 0x75, 0xce, 0xa8, 0x69, 0xb9, 0xcc, 0x8c, 0x26, 0xf3, 0xb9, 0x94, 0x45, 0xbd, 0x04, 0xd9, 0x33, 0xde, 0x84, 0x25, 0x25, 0x43, 0x66, 0x07, 0x51, 0x21,
0xa6, 0xb8, 0x11, 0x4c, 0x31, 0x3d, 0x68, 0x4b, 0x32, 0x13, 0xa0, 0x93, 0xe5, 0x41, 0x30, 0xf2, 0x63, 0x0a, 0x99, 0x84, 0x48, 0x83, 0xb1, 0xa5, 0x93, 0xcd, 0xae, 0x73, 0x46, 0x4d, 0xcb, 0x65,
0xd8, 0x41, 0x8c, 0x89, 0xfe, 0x1e, 0xac, 0x04, 0x4a, 0x30, 0xbb, 0x3d, 0xa3, 0x97, 0xb5, 0xe3, 0x66, 0x34, 0x99, 0x37, 0xc5, 0x8d, 0x60, 0x8a, 0xe9, 0x41, 0x5b, 0x92, 0x99, 0x00, 0x9d, 0x2c,
0x79, 0x5a, 0x11, 0x68, 0xda, 0xf8, 0x23, 0xc8, 0x0f, 0x89, 0x8c, 0x29, 0xc5, 0x75, 0xb4, 0x26, 0x0f, 0x82, 0x91, 0xc7, 0x0e, 0x62, 0x4c, 0xf4, 0x0f, 0x60, 0x25, 0x50, 0x82, 0xd9, 0xed, 0x19,
0xba, 0xe5, 0x6b, 0xda, 0x62, 0x3e, 0x8f, 0xdb, 0x70, 0x57, 0x49, 0x17, 0x16, 0x35, 0x8a, 0x8f, 0xbd, 0xac, 0x1d, 0xcf, 0xd3, 0x8a, 0x40, 0xd3, 0xc6, 0x1f, 0x41, 0x7e, 0x48, 0x64, 0x4c, 0x29,
0x2b, 0xa5, 0x0a, 0x04, 0x61, 0xd6, 0xf1, 0x02, 0x21, 0x27, 0xce, 0x3e, 0x68, 0xf5, 0xbd, 0x2f, 0xae, 0xa3, 0x35, 0xd1, 0x63, 0x5f, 0xd3, 0x16, 0xf3, 0x79, 0xdc, 0x86, 0xbb, 0x4a, 0xba, 0xb0,
0x0c, 0xa9, 0x7c, 0x2b, 0xd5, 0xbb, 0x62, 0x5b, 0xd8, 0x34, 0x70, 0xc9, 0x54, 0xc2, 0x8e, 0x60, 0xa8, 0x51, 0x7c, 0x5c, 0x29, 0x55, 0x20, 0x08, 0xb3, 0x8e, 0x17, 0x08, 0x39, 0x71, 0xf6, 0x41,
0x31, 0xea, 0xc9, 0xa9, 0xc2, 0x18, 0xcd, 0x7a, 0x7d, 0x6a, 0x42, 0x15, 0xc4, 0xc4, 0x40, 0x29, 0xab, 0xef, 0x7d, 0x61, 0x48, 0xe5, 0x5b, 0xa9, 0xde, 0x15, 0xdb, 0xc2, 0xa6, 0x81, 0x4b, 0xa6,
0x1c, 0xb8, 0x79, 0x2a, 0x85, 0x9d, 0x50, 0x18, 0xbf, 0x92, 0x69, 0xf5, 0x65, 0xa7, 0xa9, 0xf2, 0x12, 0x76, 0x04, 0x8b, 0x51, 0x4f, 0x4e, 0x15, 0xc6, 0x68, 0xd6, 0xeb, 0x53, 0x13, 0xaa, 0x20,
0x19, 0x31, 0xc0, 0xbb, 0x70, 0x2b, 0x1e, 0x26, 0x52, 0xa9, 0x7c, 0x20, 0x2e, 0xb0, 0x29, 0x92, 0x26, 0x06, 0x4a, 0xe1, 0xc0, 0xcd, 0x53, 0x29, 0xec, 0x84, 0xc2, 0xf8, 0x95, 0x4c, 0xab, 0x2f,
0xa4, 0x92, 0xfb, 0x61, 0x18, 0x0c, 0xb4, 0x80, 0x92, 0x4a, 0xa4, 0x0d, 0x96, 0x29, 0xbe, 0xfc, 0x3b, 0x4d, 0x95, 0xcf, 0x88, 0x01, 0xde, 0x85, 0x5b, 0xf1, 0x30, 0x91, 0x4a, 0xe5, 0x03, 0x71,
0x2f, 0xee, 0x6b, 0x10, 0x6e, 0x52, 0x09, 0xf3, 0x42, 0x61, 0xe9, 0x8f, 0x3f, 0x8c, 0x11, 0xb9, 0x81, 0x4d, 0x91, 0x24, 0x95, 0xdc, 0x0f, 0xc3, 0x60, 0xa0, 0x05, 0x94, 0x54, 0x22, 0x6d, 0xb0,
0x89, 0x31, 0x42, 0x3a, 0x49, 0x18, 0xc5, 0xbe, 0x86, 0x4b, 0x27, 0x31, 0xc2, 0x00, 0x9a, 0x16, 0x4c, 0xf1, 0xe5, 0xff, 0x71, 0x5f, 0x83, 0x70, 0x93, 0x4a, 0x98, 0x17, 0x0a, 0x4b, 0x7f, 0xfc,
0x83, 0xbd, 0x43, 0x02, 0x0c, 0x3e, 0x50, 0x17, 0x5b, 0x0f, 0xbb, 0xa9, 0x0e, 0xe3, 0xa3, 0x30, 0x61, 0x8c, 0xc8, 0x4d, 0x8c, 0x11, 0xd2, 0x49, 0xc2, 0x28, 0xf6, 0x35, 0x5c, 0x3a, 0x89, 0x11,
0x76, 0x8e, 0x45, 0xe6, 0x54, 0x82, 0x3f, 0x86, 0xd5, 0xe4, 0xa0, 0x9c, 0x46, 0xf2, 0x6b, 0x18, 0x06, 0xd0, 0xb4, 0x18, 0xec, 0x1d, 0x12, 0x60, 0xf0, 0x81, 0xba, 0xd8, 0x7a, 0xd8, 0x4d, 0x75,
0x0a, 0x41, 0x42, 0xa9, 0x7d, 0x3c, 0x2b, 0xc2, 0xcc, 0xee, 0xde, 0xfe, 0xb3, 0xda, 0x26, 0x4d, 0x18, 0x1f, 0x85, 0xb1, 0x73, 0x2c, 0x32, 0xa7, 0x12, 0xfc, 0x31, 0xac, 0x26, 0x07, 0xe5, 0x34,
0x65, 0xd7, 0xff, 0x9c, 0x83, 0xec, 0xf6, 0x01, 0xfa, 0x3e, 0x4c, 0x89, 0xe6, 0xff, 0x84, 0x6f, 0x92, 0x5f, 0xc3, 0x50, 0x08, 0x12, 0x4a, 0xed, 0x9b, 0x5a, 0x11, 0x66, 0x76, 0xf7, 0xf6, 0x9f,
0x23, 0xd6, 0xa4, 0xcf, 0x08, 0x78, 0xf9, 0xf3, 0x3f, 0xfd, 0xed, 0xcb, 0xec, 0x2d, 0x7c, 0xa3, 0xd5, 0x36, 0x69, 0x2a, 0xbb, 0xfe, 0x97, 0x1c, 0x64, 0xb7, 0x0f, 0xd0, 0x0f, 0x61, 0x4a, 0x34,
0x7a, 0xf6, 0xb6, 0xd3, 0x1d, 0x9e, 0x38, 0xd5, 0xd3, 0xb3, 0x2a, 0x7f, 0x27, 0x7c, 0x33, 0xf3, 0xff, 0x27, 0x7c, 0x1b, 0xb1, 0x26, 0x7d, 0x46, 0xc0, 0xcb, 0x9f, 0xfd, 0xf9, 0xef, 0x5f, 0x64,
0x1a, 0x3a, 0x80, 0x1c, 0xfb, 0x34, 0x90, 0xf8, 0xe1, 0xc4, 0x4a, 0xfe, 0xbc, 0x80, 0x2d, 0x2e, 0x6f, 0xe1, 0x1b, 0xd5, 0xb3, 0xb7, 0x9d, 0xee, 0xf0, 0xc4, 0xa9, 0x9e, 0x9e, 0x55, 0xf9, 0x3b,
0x79, 0x11, 0x5f, 0xd7, 0x25, 0x0f, 0x47, 0x3e, 0x93, 0xdb, 0x84, 0xa2, 0xf6, 0x85, 0x00, 0x5d, 0xe1, 0xdb, 0x99, 0xd7, 0xd0, 0x01, 0xe4, 0xd8, 0xa7, 0x81, 0xc4, 0x0f, 0x27, 0x56, 0xf2, 0xe7,
0xfa, 0x49, 0xc5, 0xba, 0xfc, 0xeb, 0x03, 0xbe, 0xc6, 0xb4, 0x6d, 0x9e, 0xf7, 0xe3, 0xda, 0x86, 0x05, 0x6c, 0x71, 0xc9, 0x8b, 0xf8, 0xba, 0x2e, 0x79, 0x38, 0xf2, 0x99, 0xdc, 0x26, 0x14, 0xb5,
0x1d, 0xed, 0xb8, 0xb6, 0x5a, 0x17, 0xd9, 0xac, 0xad, 0x7f, 0xde, 0x67, 0xda, 0x0e, 0xe4, 0x37, 0x2f, 0x04, 0xe8, 0xd2, 0x4f, 0x2a, 0xd6, 0xe5, 0x5f, 0x1f, 0xf0, 0x35, 0xa6, 0x6d, 0xf3, 0xbc,
0x8b, 0x96, 0x8f, 0xee, 0x1a, 0x5a, 0xe0, 0x7a, 0xb3, 0xd7, 0x5a, 0x4d, 0x66, 0x90, 0x48, 0xf7, 0x1f, 0xd7, 0x36, 0xec, 0x68, 0xc7, 0xb5, 0xd5, 0xba, 0xc8, 0x66, 0x6d, 0xfd, 0xf3, 0x3e, 0xd3,
0x38, 0xd2, 0x6d, 0x7c, 0x4b, 0x47, 0x6a, 0x05, 0x7c, 0x14, 0x70, 0xfd, 0x04, 0xa6, 0x78, 0xa7, 0x76, 0x20, 0xbf, 0x59, 0xb4, 0x7c, 0x74, 0xd7, 0xd0, 0x02, 0xd7, 0x9b, 0xbd, 0xd6, 0x6a, 0x32,
0x0c, 0x1d, 0xaa, 0x07, 0xcb, 0xd0, 0x47, 0x4c, 0x38, 0xdf, 0x48, 0x8f, 0x0d, 0x2f, 0x71, 0xb4, 0x83, 0x44, 0xba, 0xc7, 0x91, 0x6e, 0xe3, 0x5b, 0x3a, 0x52, 0x2b, 0xe0, 0xa3, 0x80, 0xeb, 0x27,
0x05, 0x5c, 0x0e, 0xd0, 0x78, 0xb3, 0x8c, 0xa2, 0x3c, 0xc9, 0xfc, 0x5f, 0x66, 0xfd, 0x5f, 0x59, 0x30, 0xc5, 0x3b, 0x65, 0xe8, 0x50, 0x3d, 0x58, 0x86, 0x3e, 0x62, 0xc2, 0xf9, 0x46, 0x7a, 0x6c,
0x98, 0xe2, 0x2d, 0x15, 0x34, 0x04, 0x08, 0x7b, 0x4f, 0xf1, 0x7d, 0x8e, 0x75, 0xb3, 0xe2, 0xfb, 0x78, 0x89, 0xa3, 0x2d, 0xe0, 0x72, 0x80, 0xc6, 0x9b, 0x65, 0x14, 0xe5, 0x49, 0xe6, 0x1b, 0x99,
0x1c, 0x6f, 0x5b, 0xe1, 0xbb, 0x1c, 0x79, 0x09, 0x2f, 0x06, 0xc8, 0xfc, 0xe3, 0x66, 0xf5, 0x98, 0xf5, 0x7f, 0x67, 0x61, 0x8a, 0xb7, 0x54, 0xd0, 0x10, 0x20, 0xec, 0x3d, 0xc5, 0xf7, 0x39, 0xd6,
0x71, 0x31, 0xb3, 0xbe, 0x84, 0xa2, 0xd6, 0x43, 0x42, 0x26, 0x89, 0x91, 0x26, 0x54, 0xfc, 0x12, 0xcd, 0x8a, 0xef, 0x73, 0xbc, 0x6d, 0x85, 0xef, 0x72, 0xe4, 0x25, 0xbc, 0x18, 0x20, 0xf3, 0x8f,
0x18, 0x1a, 0x50, 0xf8, 0x3e, 0x07, 0xbd, 0x83, 0x2b, 0xba, 0x71, 0x05, 0xae, 0xcb, 0x39, 0x19, 0x9b, 0xd5, 0x63, 0xc6, 0xc5, 0xcc, 0xfa, 0x12, 0x8a, 0x5a, 0x0f, 0x09, 0x99, 0x24, 0x46, 0x9a,
0xf0, 0x8f, 0x69, 0x49, 0x14, 0xed, 0x23, 0xa1, 0xfb, 0x06, 0xd1, 0xf1, 0x76, 0x94, 0xf5, 0x60, 0x50, 0xf1, 0x4b, 0x60, 0x68, 0x40, 0xe1, 0xfb, 0x1c, 0xf4, 0x0e, 0xae, 0xe8, 0xc6, 0x15, 0xb8,
0x32, 0x53, 0xa2, 0x0a, 0x02, 0xff, 0x94, 0x72, 0x3a, 0x8c, 0x53, 0xd9, 0xfe, 0xdf, 0xec, 0x5b, 0x2e, 0xe7, 0x64, 0xc0, 0x3f, 0xa3, 0x25, 0x51, 0xb4, 0x8f, 0x84, 0xee, 0x1b, 0x44, 0xc7, 0xdb,
0x98, 0xf8, 0x21, 0x03, 0xf2, 0xa1, 0x10, 0x74, 0x73, 0xd0, 0x8a, 0xa9, 0xd2, 0x0f, 0xd3, 0x60, 0x51, 0xd6, 0x83, 0xc9, 0x4c, 0x89, 0x2a, 0x08, 0xfc, 0x53, 0xca, 0xe9, 0x30, 0x4e, 0x65, 0xfb,
0xeb, 0x6e, 0xe2, 0xbc, 0x54, 0xe1, 0x11, 0x57, 0x61, 0x15, 0xdf, 0x0e, 0x54, 0x90, 0x3f, 0x98, 0xff, 0xb0, 0x6f, 0x61, 0xe2, 0xe7, 0x0f, 0xc8, 0x87, 0x42, 0xd0, 0xcd, 0x41, 0x2b, 0xa6, 0x4a,
0xa8, 0x8a, 0x82, 0xb6, 0xea, 0xb4, 0xdb, 0xcc, 0x10, 0x3f, 0xa2, 0x25, 0xbd, 0xde, 0xa4, 0x41, 0x3f, 0x4c, 0x83, 0xad, 0xbb, 0x89, 0xf3, 0x52, 0x85, 0x47, 0x5c, 0x85, 0x55, 0x7c, 0x3b, 0x50,
0xf7, 0x8c, 0x3d, 0x06, 0xbd, 0xcf, 0x63, 0xe1, 0x49, 0x2c, 0x12, 0xff, 0x55, 0x8e, 0x7f, 0x1f, 0x41, 0xfe, 0xcc, 0xa2, 0x2a, 0x0a, 0xda, 0xaa, 0xd3, 0x6e, 0x33, 0x43, 0xfc, 0x94, 0x96, 0xf4,
0xaf, 0x24, 0xe1, 0xbb, 0x9c, 0x3f, 0xaa, 0x82, 0x68, 0xcb, 0x98, 0x55, 0x88, 0x74, 0x7d, 0xcc, 0x7a, 0x93, 0x06, 0xdd, 0x33, 0xf6, 0x18, 0xf4, 0x3e, 0x8f, 0x85, 0x27, 0xb1, 0x48, 0xfc, 0x57,
0x2a, 0x44, 0xbb, 0x3a, 0x97, 0xab, 0x30, 0xe2, 0xfc, 0x4c, 0x85, 0x73, 0x80, 0xb0, 0x6b, 0x83, 0x39, 0xfe, 0x7d, 0xbc, 0x92, 0x84, 0xef, 0x72, 0xfe, 0xa8, 0x0a, 0xa2, 0x2d, 0x63, 0x56, 0x21,
0x8c, 0xc6, 0xd5, 0x0a, 0x83, 0xf8, 0xcd, 0x1f, 0x6f, 0xf8, 0xe0, 0xc7, 0x1c, 0xfb, 0x1e, 0x5e, 0xd2, 0xf5, 0x31, 0xab, 0x10, 0xed, 0xea, 0x5c, 0xae, 0xc2, 0x88, 0xf3, 0x33, 0x15, 0xce, 0x01,
0x4e, 0xc2, 0xee, 0x52, 0x6e, 0xe6, 0xe7, 0xbf, 0xcd, 0x43, 0xf1, 0x03, 0xa7, 0xd3, 0xf7, 0x49, 0xc2, 0xae, 0x0d, 0x32, 0x1a, 0x57, 0x2b, 0x0c, 0xe2, 0x37, 0x7f, 0xbc, 0xe1, 0x83, 0x1f, 0x73,
0x9f, 0x35, 0xa3, 0xd1, 0x31, 0x4c, 0xf1, 0xc8, 0x1f, 0x77, 0x77, 0xbd, 0x95, 0x12, 0x77, 0xf7, 0xec, 0x7b, 0x78, 0x39, 0x09, 0xbb, 0x4b, 0xb9, 0x99, 0x9f, 0xff, 0x3e, 0x0f, 0xc5, 0x0f, 0x9c,
0x48, 0x9f, 0x01, 0x3f, 0xe4, 0xd0, 0x77, 0xb1, 0x15, 0x40, 0xf7, 0x42, 0xf9, 0x55, 0xde, 0x23, 0x4e, 0xdf, 0x27, 0x7d, 0xd6, 0x8c, 0x46, 0xc7, 0x30, 0xc5, 0x23, 0x7f, 0xdc, 0xdd, 0xf5, 0x56,
0x60, 0x5b, 0x3e, 0x85, 0x69, 0xd1, 0x13, 0x40, 0x31, 0x69, 0x91, 0xde, 0x81, 0xb5, 0x6c, 0x9e, 0x4a, 0xdc, 0xdd, 0x23, 0x7d, 0x06, 0xfc, 0x90, 0x43, 0xdf, 0xc5, 0x56, 0x00, 0xdd, 0x0b, 0xe5,
0x4c, 0xbc, 0x65, 0x3a, 0x96, 0xc7, 0x99, 0x19, 0xd8, 0x0f, 0x00, 0xc2, 0x26, 0x54, 0xdc, 0xbe, 0x57, 0x79, 0x8f, 0x80, 0x6d, 0xf9, 0x14, 0xa6, 0x45, 0x4f, 0x00, 0xc5, 0xa4, 0x45, 0x7a, 0x07,
0x63, 0x3d, 0x2b, 0x6b, 0x35, 0x99, 0x41, 0x02, 0xbf, 0xc6, 0x81, 0x1f, 0xe0, 0xbb, 0x46, 0xe0, 0xd6, 0xb2, 0x79, 0x32, 0xf1, 0x96, 0xe9, 0x58, 0x1e, 0x67, 0x66, 0x60, 0x3f, 0x02, 0x08, 0x9b,
0x76, 0xb0, 0x80, 0x81, 0xb7, 0x20, 0xcf, 0xbe, 0x74, 0xa1, 0x58, 0xe8, 0xd7, 0x3e, 0x86, 0x59, 0x50, 0x71, 0xfb, 0x8e, 0xf5, 0xac, 0xac, 0xd5, 0x64, 0x06, 0x09, 0xfc, 0x1a, 0x07, 0x7e, 0x80,
0x96, 0x69, 0x4a, 0x42, 0x3d, 0xe0, 0x50, 0x2b, 0x78, 0xc9, 0x08, 0xc5, 0xbe, 0x78, 0x31, 0x90, 0xef, 0x1a, 0x81, 0xdb, 0xc1, 0x02, 0x06, 0xde, 0x82, 0x3c, 0xfb, 0xd2, 0x85, 0x62, 0xa1, 0x5f,
0x11, 0xcc, 0xaa, 0x0f, 0x5c, 0xe8, 0x4e, 0xcc, 0x66, 0xd1, 0x8f, 0x61, 0xd6, 0x4a, 0xd2, 0xb4, 0xfb, 0x18, 0x66, 0x59, 0xa6, 0x29, 0x09, 0xf5, 0x80, 0x43, 0xad, 0xe0, 0x25, 0x23, 0x14, 0xfb,
0x04, 0x7c, 0xc2, 0x01, 0x31, 0xbe, 0x63, 0x36, 0xaa, 0x64, 0xa7, 0xa0, 0x34, 0x80, 0xfc, 0x74, 0xe2, 0xc5, 0x40, 0x46, 0x30, 0xab, 0x3e, 0x70, 0xa1, 0x3b, 0x31, 0x9b, 0x45, 0x3f, 0x86, 0x59,
0x1e, 0xf2, 0x2c, 0x07, 0x61, 0xb1, 0x3b, 0x2c, 0xdd, 0xe2, 0x16, 0x1e, 0x6b, 0x98, 0xc4, 0x2d, 0x2b, 0x49, 0xd3, 0x12, 0xf0, 0x09, 0x07, 0xc4, 0xf8, 0x8e, 0xd9, 0xa8, 0x92, 0x9d, 0x82, 0xd2,
0x3c, 0x5e, 0xf5, 0x19, 0x62, 0x37, 0xff, 0x39, 0x17, 0xe1, 0x5c, 0x6c, 0xc7, 0x3e, 0x14, 0xb5, 0x00, 0xf2, 0x8b, 0x79, 0xc8, 0xb3, 0x1c, 0x84, 0xc5, 0xee, 0xb0, 0x74, 0x8b, 0x5b, 0x78, 0xac,
0x02, 0x0f, 0x19, 0x24, 0x46, 0xdb, 0x31, 0xf1, 0xd8, 0x6d, 0xa8, 0x0e, 0xf1, 0x2a, 0x07, 0xb5, 0x61, 0x12, 0xb7, 0xf0, 0x78, 0xd5, 0x67, 0x88, 0xdd, 0xfc, 0x47, 0x60, 0x84, 0x73, 0xb1, 0x1d,
0xf0, 0xcd, 0x28, 0x68, 0x5b, 0xb0, 0x31, 0xd4, 0x1f, 0x42, 0x49, 0xaf, 0x04, 0x91, 0x41, 0x68, 0xfb, 0x50, 0xd4, 0x0a, 0x3c, 0x64, 0x90, 0x18, 0x6d, 0xc7, 0xc4, 0x63, 0xb7, 0xa1, 0x3a, 0xc4,
0xac, 0xdf, 0x13, 0x8f, 0x15, 0xa6, 0x42, 0xd2, 0xe0, 0x34, 0xc1, 0x8f, 0xd7, 0x14, 0x2f, 0x43, 0xab, 0x1c, 0xd4, 0xc2, 0x37, 0xa3, 0xa0, 0x6d, 0xc1, 0xc6, 0x50, 0x7f, 0x0c, 0x25, 0xbd, 0x12,
0xff, 0x04, 0x66, 0x64, 0x7d, 0x68, 0xda, 0x6f, 0xb4, 0x43, 0x64, 0xda, 0x6f, 0xac, 0xb8, 0x34, 0x44, 0x06, 0xa1, 0xb1, 0x7e, 0x4f, 0x3c, 0x56, 0x98, 0x0a, 0x49, 0x83, 0xd3, 0x04, 0x3f, 0x79,
0x24, 0x02, 0x1c, 0x96, 0xe5, 0xc1, 0x2a, 0x40, 0x4b, 0x48, 0x5a, 0x46, 0x24, 0x41, 0x86, 0x3d, 0x53, 0xbc, 0x0c, 0xfd, 0x13, 0x98, 0x91, 0xf5, 0xa1, 0x69, 0xbf, 0xd1, 0x0e, 0x91, 0x69, 0xbf,
0x8f, 0x24, 0x48, 0xad, 0x06, 0x99, 0x08, 0x79, 0x4c, 0x7c, 0x79, 0x97, 0x55, 0x82, 0x8f, 0x12, 0xb1, 0xe2, 0xd2, 0x90, 0x08, 0x70, 0x58, 0x96, 0x07, 0xab, 0x00, 0x2d, 0x21, 0x69, 0x19, 0x91,
0x24, 0xea, 0xd1, 0x10, 0x4f, 0x62, 0x91, 0xa8, 0x98, 0xa3, 0x2e, 0xe3, 0x57, 0x0c, 0xa8, 0x32, 0x04, 0x19, 0xf6, 0x3c, 0x92, 0x20, 0xb5, 0x1a, 0x64, 0x22, 0xe4, 0x31, 0xf1, 0xe5, 0x5d, 0x56,
0x14, 0xa2, 0xcf, 0x00, 0xc2, 0x62, 0x36, 0xfe, 0x3a, 0x36, 0x76, 0xc4, 0xe2, 0xaf, 0x63, 0x73, 0x09, 0x3e, 0x4a, 0x90, 0xa8, 0x47, 0x43, 0x3c, 0x89, 0x45, 0xa2, 0x62, 0x8e, 0xba, 0x8c, 0x5f,
0x3d, 0x6c, 0xf0, 0xe0, 0x10, 0x5c, 0xfc, 0xcc, 0x85, 0xc1, 0xff, 0x2c, 0x03, 0x68, 0xbc, 0xf8, 0x31, 0xa0, 0xca, 0x50, 0x88, 0x7e, 0x02, 0x10, 0x16, 0xb3, 0xf1, 0xd7, 0xb1, 0xb1, 0x23, 0x16,
0x45, 0xaf, 0x9b, 0x21, 0x8c, 0xcd, 0x36, 0xeb, 0x8d, 0xab, 0x31, 0x27, 0x46, 0xcf, 0x50, 0xaf, 0x7f, 0x1d, 0x9b, 0xeb, 0x61, 0x83, 0x07, 0x87, 0xe0, 0xe2, 0x67, 0x2e, 0x0c, 0xfe, 0x97, 0x19,
0x16, 0x5f, 0x32, 0x7c, 0xc9, 0x34, 0xfb, 0x22, 0x03, 0x73, 0x91, 0xf2, 0x19, 0x3d, 0x4a, 0x38, 0x40, 0xe3, 0xc5, 0x2f, 0x7a, 0xdd, 0x0c, 0x61, 0x6c, 0xb6, 0x59, 0x6f, 0x5c, 0x8d, 0x39, 0x31,
0xe7, 0x58, 0xc3, 0xce, 0x7a, 0x7c, 0x29, 0x5f, 0x62, 0xc6, 0xa2, 0xdd, 0x0a, 0x95, 0xad, 0xfd, 0x7a, 0x86, 0x7a, 0xb5, 0xf8, 0x92, 0xe1, 0x4b, 0xa6, 0xd9, 0xe7, 0x19, 0x98, 0x8b, 0x94, 0xcf,
0x84, 0x26, 0x4d, 0xd1, 0x9a, 0x1b, 0x25, 0x00, 0x8c, 0x75, 0xfd, 0xac, 0x27, 0x97, 0x33, 0x5e, 0xe8, 0x51, 0xc2, 0x39, 0xc7, 0x1a, 0x76, 0xd6, 0xe3, 0x4b, 0xf9, 0x12, 0x33, 0x16, 0xed, 0x56,
0xe1, 0xb4, 0xc2, 0x04, 0x8e, 0xba, 0x85, 0x2c, 0xd5, 0x4d, 0x6e, 0x11, 0x6d, 0x1a, 0x9a, 0xdc, 0xa8, 0x6c, 0xed, 0xe7, 0x34, 0x69, 0x8a, 0xd6, 0xdc, 0x28, 0x01, 0x60, 0xac, 0xeb, 0x67, 0x3d,
0x22, 0x56, 0xe7, 0x27, 0xb9, 0x05, 0xab, 0x7a, 0x35, 0x4f, 0x94, 0x05, 0x7d, 0x12, 0xe4, 0x64, 0xb9, 0x9c, 0xf1, 0x0a, 0xa7, 0x15, 0x26, 0x70, 0xd4, 0x2d, 0x64, 0xa9, 0x6e, 0x72, 0x8b, 0x68,
0x4f, 0x8c, 0x75, 0x03, 0x26, 0x42, 0x86, 0x9e, 0xa8, 0xca, 0x79, 0x94, 0x20, 0xf1, 0x12, 0x4f, 0xd3, 0xd0, 0xe4, 0x16, 0xb1, 0x3a, 0x3f, 0xc9, 0x2d, 0x58, 0xd5, 0xab, 0x79, 0xa2, 0x2c, 0xe8,
0x8c, 0x77, 0x03, 0x92, 0x3c, 0x91, 0xa3, 0x6a, 0x9e, 0x18, 0x56, 0xdf, 0x26, 0x4f, 0x1c, 0x6b, 0x93, 0x20, 0x27, 0x7b, 0x62, 0xac, 0x1b, 0x30, 0x11, 0x32, 0xf4, 0x44, 0x55, 0xce, 0xa3, 0x04,
0x89, 0x9a, 0x3c, 0x71, 0xbc, 0x80, 0x4f, 0x3a, 0x5b, 0x0e, 0x1e, 0xf1, 0xc4, 0x05, 0x43, 0xb5, 0x89, 0x97, 0x78, 0x62, 0xbc, 0x1b, 0x90, 0xe4, 0x89, 0x1c, 0x55, 0xf3, 0xc4, 0xb0, 0xfa, 0x36,
0x8e, 0xde, 0x48, 0xb0, 0xa9, 0xb1, 0xdd, 0x6a, 0xbd, 0x79, 0x45, 0xee, 0xc9, 0x1e, 0x20, 0x4e, 0x79, 0xe2, 0x58, 0x4b, 0xd4, 0xe4, 0x89, 0xe3, 0x05, 0x7c, 0xd2, 0xd9, 0x72, 0xf0, 0x88, 0x27,
0x43, 0x79, 0xc0, 0x2f, 0x33, 0xb0, 0x68, 0x2a, 0xf7, 0x51, 0x02, 0x58, 0x42, 0xaf, 0xd6, 0x5a, 0x2e, 0x18, 0xaa, 0x75, 0xf4, 0x46, 0x82, 0x4d, 0x8d, 0xed, 0x56, 0xeb, 0xcd, 0x2b, 0x72, 0x4f,
0xbb, 0x2a, 0xfb, 0x15, 0xec, 0x16, 0xf8, 0xc4, 0x46, 0xe9, 0x77, 0x7f, 0x5d, 0xc9, 0xfc, 0x91, 0xf6, 0x00, 0x71, 0x1a, 0xca, 0x03, 0x7e, 0x93, 0x81, 0x45, 0x53, 0xb9, 0x8f, 0x12, 0xc0, 0x12,
0xfe, 0xfb, 0x0b, 0xfd, 0x77, 0x34, 0xcd, 0x7f, 0x4f, 0xfd, 0xf6, 0x7f, 0x02, 0x00, 0x00, 0xff, 0x7a, 0xb5, 0xd6, 0xda, 0x55, 0xd9, 0xaf, 0x60, 0xb7, 0xc0, 0x27, 0x36, 0x4a, 0x7f, 0xf8, 0xdb,
0xff, 0x23, 0x65, 0x8c, 0x0e, 0xd6, 0x2d, 0x00, 0x00, 0x4a, 0xe6, 0x4b, 0xfa, 0xef, 0xaf, 0xf4, 0xdf, 0xd1, 0x34, 0xff, 0x15, 0xf6, 0xdb, 0xff, 0x0d,
0x00, 0x00, 0xff, 0xff, 0x7b, 0x02, 0x74, 0xf8, 0x0c, 0x2e, 0x00, 0x00,
} }

View File

@ -367,14 +367,20 @@ message RangeRequest {
// keys_only when set returns only the keys and not the values. // keys_only when set returns only the keys and not the values.
bool keys_only = 8; bool keys_only = 8;
// count_only when set returns only the count of the keys in the range.
bool count_only = 9;
} }
message RangeResponse { message RangeResponse {
ResponseHeader header = 1; ResponseHeader header = 1;
// kvs is the list of key-value pairs matched by the range request. // kvs is the list of key-value pairs matched by the range request.
// kvs is empty when count is requested.
repeated mvccpb.KeyValue kvs = 2; repeated mvccpb.KeyValue kvs = 2;
// more indicates if there are more keys to return in the requested range. // more indicates if there are more keys to return in the requested range.
bool more = 3; bool more = 3;
// count is set to the number of keys within the range when requested.
int64 count = 4;
} }
message PutRequest { message PutRequest {

View File

@ -20,6 +20,18 @@ import (
"github.com/coreos/etcd/mvcc/mvccpb" "github.com/coreos/etcd/mvcc/mvccpb"
) )
type RangeOptions struct {
Limit int64
Rev int64
Count bool
}
type RangeResult struct {
KVs []mvccpb.KeyValue
Rev int64
Count int
}
type KV interface { type KV interface {
// Rev returns the current revision of the KV. // Rev returns the current revision of the KV.
Rev() int64 Rev() int64
@ -37,7 +49,7 @@ type KV interface {
// If `end` is not nil and empty, it gets the keys greater than or equal to key. // If `end` is not nil and empty, it gets the keys greater than or equal to key.
// Limit limits the number of keys returned. // Limit limits the number of keys returned.
// If the required rev is compacted, ErrCompacted will be returned. // If the required rev is compacted, ErrCompacted will be returned.
Range(key, end []byte, limit, rangeRev int64) (kvs []mvccpb.KeyValue, rev int64, err error) Range(key, end []byte, ro RangeOptions) (r *RangeResult, err error)
// Put puts the given key, value into the store. Put also takes additional argument lease to // Put puts the given key, value into the store. Put also takes additional argument lease to
// attach a lease to a key-value pair as meta-data. KV implementation does not validate the lease // attach a lease to a key-value pair as meta-data. KV implementation does not validate the lease
@ -63,7 +75,7 @@ type KV interface {
// TxnEnd ends the on-going txn with txn ID. If the on-going txn ID is not matched, error is returned. // TxnEnd ends the on-going txn with txn ID. If the on-going txn ID is not matched, error is returned.
TxnEnd(txnID int64) error TxnEnd(txnID int64) error
// TxnRange returns the current revision of the KV when the operation is executed. // TxnRange returns the current revision of the KV when the operation is executed.
TxnRange(txnID int64, key, end []byte, limit, rangeRev int64) (kvs []mvccpb.KeyValue, rev int64, err error) TxnRange(txnID int64, key, end []byte, ro RangeOptions) (r *RangeResult, err error)
TxnPut(txnID int64, key, value []byte, lease lease.LeaseID) (rev int64, err error) TxnPut(txnID int64, key, value []byte, lease lease.LeaseID) (rev int64, err error)
TxnDeleteRange(txnID int64, key, end []byte) (n, rev int64, err error) TxnDeleteRange(txnID int64, key, end []byte) (n, rev int64, err error)

View File

@ -33,19 +33,19 @@ import (
// TODO: add similar tests on operations in one txn/rev // TODO: add similar tests on operations in one txn/rev
type ( type (
rangeFunc func(kv KV, key, end []byte, limit, rangeRev int64) ([]mvccpb.KeyValue, int64, error) rangeFunc func(kv KV, key, end []byte, ro RangeOptions) (*RangeResult, error)
putFunc func(kv KV, key, value []byte, lease lease.LeaseID) int64 putFunc func(kv KV, key, value []byte, lease lease.LeaseID) int64
deleteRangeFunc func(kv KV, key, end []byte) (n, rev int64) deleteRangeFunc func(kv KV, key, end []byte) (n, rev int64)
) )
var ( var (
normalRangeFunc = func(kv KV, key, end []byte, limit, rangeRev int64) ([]mvccpb.KeyValue, int64, error) { normalRangeFunc = func(kv KV, key, end []byte, ro RangeOptions) (*RangeResult, error) {
return kv.Range(key, end, limit, rangeRev) return kv.Range(key, end, ro)
} }
txnRangeFunc = func(kv KV, key, end []byte, limit, rangeRev int64) ([]mvccpb.KeyValue, int64, error) { txnRangeFunc = func(kv KV, key, end []byte, ro RangeOptions) (*RangeResult, error) {
id := kv.TxnBegin() id := kv.TxnBegin()
defer kv.TxnEnd(id) defer kv.TxnEnd(id)
return kv.TxnRange(id, key, end, limit, rangeRev) return kv.TxnRange(id, key, end, ro)
} }
normalPutFunc = func(kv KV, key, value []byte, lease lease.LeaseID) int64 { normalPutFunc = func(kv KV, key, value []byte, lease lease.LeaseID) int64 {
@ -128,15 +128,15 @@ func testKVRange(t *testing.T, f rangeFunc) {
} }
for i, tt := range tests { for i, tt := range tests {
kvs, rev, err := f(s, tt.key, tt.end, 0, 0) r, err := f(s, tt.key, tt.end, RangeOptions{})
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
if rev != wrev { if r.Rev != wrev {
t.Errorf("#%d: rev = %d, want %d", i, rev, wrev) t.Errorf("#%d: rev = %d, want %d", i, r.Rev, wrev)
} }
if !reflect.DeepEqual(kvs, tt.wkvs) { if !reflect.DeepEqual(r.KVs, tt.wkvs) {
t.Errorf("#%d: kvs = %+v, want %+v", i, kvs, tt.wkvs) t.Errorf("#%d: kvs = %+v, want %+v", i, r.KVs, tt.wkvs)
} }
} }
} }
@ -164,15 +164,15 @@ func testKVRangeRev(t *testing.T, f rangeFunc) {
} }
for i, tt := range tests { for i, tt := range tests {
kvs, rev, err := f(s, []byte("foo"), []byte("foo3"), 0, tt.rev) r, err := f(s, []byte("foo"), []byte("foo3"), RangeOptions{Rev: tt.rev})
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
if rev != tt.wrev { if r.Rev != tt.wrev {
t.Errorf("#%d: rev = %d, want %d", i, rev, tt.wrev) t.Errorf("#%d: rev = %d, want %d", i, r.Rev, tt.wrev)
} }
if !reflect.DeepEqual(kvs, tt.wkvs) { if !reflect.DeepEqual(r.KVs, tt.wkvs) {
t.Errorf("#%d: kvs = %+v, want %+v", i, kvs, tt.wkvs) t.Errorf("#%d: kvs = %+v, want %+v", i, r.KVs, tt.wkvs)
} }
} }
} }
@ -203,7 +203,7 @@ func testKVRangeBadRev(t *testing.T, f rangeFunc) {
{100, ErrFutureRev}, {100, ErrFutureRev},
} }
for i, tt := range tests { for i, tt := range tests {
_, _, err := f(s, []byte("foo"), []byte("foo3"), 0, tt.rev) _, err := f(s, []byte("foo"), []byte("foo3"), RangeOptions{Rev: tt.rev})
if err != tt.werr { if err != tt.werr {
t.Errorf("#%d: error = %v, want %v", i, err, tt.werr) t.Errorf("#%d: error = %v, want %v", i, err, tt.werr)
} }
@ -235,15 +235,15 @@ func testKVRangeLimit(t *testing.T, f rangeFunc) {
{100, kvs}, {100, kvs},
} }
for i, tt := range tests { for i, tt := range tests {
kvs, rev, err := f(s, []byte("foo"), []byte("foo3"), tt.limit, 0) r, err := f(s, []byte("foo"), []byte("foo3"), RangeOptions{Limit: tt.limit})
if err != nil { if err != nil {
t.Fatalf("#%d: range error (%v)", i, err) t.Fatalf("#%d: range error (%v)", i, err)
} }
if !reflect.DeepEqual(kvs, tt.wkvs) { if !reflect.DeepEqual(r.KVs, tt.wkvs) {
t.Errorf("#%d: kvs = %+v, want %+v", i, kvs, tt.wkvs) t.Errorf("#%d: kvs = %+v, want %+v", i, r.KVs, tt.wkvs)
} }
if rev != wrev { if r.Rev != wrev {
t.Errorf("#%d: rev = %d, want %d", i, rev, wrev) t.Errorf("#%d: rev = %d, want %d", i, r.Rev, wrev)
} }
} }
} }
@ -264,15 +264,15 @@ func testKVPutMultipleTimes(t *testing.T, f putFunc) {
t.Errorf("#%d: rev = %d, want %d", i, rev, base+1) t.Errorf("#%d: rev = %d, want %d", i, rev, base+1)
} }
kvs, _, err := s.Range([]byte("foo"), nil, 0, 0) r, err := s.Range([]byte("foo"), nil, RangeOptions{})
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
wkvs := []mvccpb.KeyValue{ wkvs := []mvccpb.KeyValue{
{Key: []byte("foo"), Value: []byte("bar"), CreateRevision: 2, ModRevision: base + 1, Version: base, Lease: base}, {Key: []byte("foo"), Value: []byte("bar"), CreateRevision: 2, ModRevision: base + 1, Version: base, Lease: base},
} }
if !reflect.DeepEqual(kvs, wkvs) { if !reflect.DeepEqual(r.KVs, wkvs) {
t.Errorf("#%d: kvs = %+v, want %+v", i, kvs, wkvs) t.Errorf("#%d: kvs = %+v, want %+v", i, r.KVs, wkvs)
} }
} }
} }
@ -368,17 +368,17 @@ func TestKVOperationInSequence(t *testing.T) {
t.Errorf("#%d: put rev = %d, want %d", i, rev, base+1) t.Errorf("#%d: put rev = %d, want %d", i, rev, base+1)
} }
kvs, rev, err := s.Range([]byte("foo"), nil, 0, base+1) r, err := s.Range([]byte("foo"), nil, RangeOptions{Rev: base + 1})
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
wkvs := []mvccpb.KeyValue{ wkvs := []mvccpb.KeyValue{
{Key: []byte("foo"), Value: []byte("bar"), CreateRevision: base + 1, ModRevision: base + 1, Version: 1, Lease: int64(lease.NoLease)}, {Key: []byte("foo"), Value: []byte("bar"), CreateRevision: base + 1, ModRevision: base + 1, Version: 1, Lease: int64(lease.NoLease)},
} }
if !reflect.DeepEqual(kvs, wkvs) { if !reflect.DeepEqual(r.KVs, wkvs) {
t.Errorf("#%d: kvs = %+v, want %+v", i, kvs, wkvs) t.Errorf("#%d: kvs = %+v, want %+v", i, r.KVs, wkvs)
} }
if rev != base+1 { if r.Rev != base+1 {
t.Errorf("#%d: range rev = %d, want %d", i, rev, base+1) t.Errorf("#%d: range rev = %d, want %d", i, rev, base+1)
} }
@ -388,15 +388,15 @@ func TestKVOperationInSequence(t *testing.T) {
t.Errorf("#%d: n = %d, rev = %d, want (%d, %d)", i, n, rev, 1, base+2) t.Errorf("#%d: n = %d, rev = %d, want (%d, %d)", i, n, rev, 1, base+2)
} }
kvs, rev, err = s.Range([]byte("foo"), nil, 0, base+2) r, err = s.Range([]byte("foo"), nil, RangeOptions{Rev: base + 2})
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
if kvs != nil { if r.KVs != nil {
t.Errorf("#%d: kvs = %+v, want %+v", i, kvs, nil) t.Errorf("#%d: kvs = %+v, want %+v", i, r.KVs, nil)
} }
if rev != base+2 { if r.Rev != base+2 {
t.Errorf("#%d: range rev = %d, want %d", i, rev, base+2) t.Errorf("#%d: range rev = %d, want %d", i, r.Rev, base+2)
} }
} }
} }
@ -406,7 +406,7 @@ func TestKVTxnBlockNonTxnOperations(t *testing.T) {
s := NewStore(b, &lease.FakeLessor{}, nil) s := NewStore(b, &lease.FakeLessor{}, nil)
tests := []func(){ tests := []func(){
func() { s.Range([]byte("foo"), nil, 0, 0) }, func() { s.Range([]byte("foo"), nil, RangeOptions{}) },
func() { s.Put([]byte("foo"), nil, lease.NoLease) }, func() { s.Put([]byte("foo"), nil, lease.NoLease) },
func() { s.DeleteRange([]byte("foo"), nil) }, func() { s.DeleteRange([]byte("foo"), nil) },
} }
@ -445,7 +445,7 @@ func TestKVTxnWrongID(t *testing.T) {
tests := []func() error{ tests := []func() error{
func() error { func() error {
_, _, err := s.TxnRange(wrongid, []byte("foo"), nil, 0, 0) _, err := s.TxnRange(wrongid, []byte("foo"), nil, RangeOptions{})
return err return err
}, },
func() error { func() error {
@ -490,18 +490,18 @@ func TestKVTxnOperationInSequence(t *testing.T) {
t.Errorf("#%d: put rev = %d, want %d", i, rev, base+1) t.Errorf("#%d: put rev = %d, want %d", i, rev, base+1)
} }
kvs, rev, err := s.TxnRange(id, []byte("foo"), nil, 0, base+1) r, err := s.TxnRange(id, []byte("foo"), nil, RangeOptions{Rev: base + 1})
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
wkvs := []mvccpb.KeyValue{ wkvs := []mvccpb.KeyValue{
{Key: []byte("foo"), Value: []byte("bar"), CreateRevision: base + 1, ModRevision: base + 1, Version: 1, Lease: int64(lease.NoLease)}, {Key: []byte("foo"), Value: []byte("bar"), CreateRevision: base + 1, ModRevision: base + 1, Version: 1, Lease: int64(lease.NoLease)},
} }
if !reflect.DeepEqual(kvs, wkvs) { if !reflect.DeepEqual(r.KVs, wkvs) {
t.Errorf("#%d: kvs = %+v, want %+v", i, kvs, wkvs) t.Errorf("#%d: kvs = %+v, want %+v", i, r.KVs, wkvs)
} }
if rev != base+1 { if r.Rev != base+1 {
t.Errorf("#%d: range rev = %d, want %d", i, rev, base+1) t.Errorf("#%d: range rev = %d, want %d", i, r.Rev, base+1)
} }
// delete foo // delete foo
@ -513,15 +513,15 @@ func TestKVTxnOperationInSequence(t *testing.T) {
t.Errorf("#%d: n = %d, rev = %d, want (%d, %d)", i, n, rev, 1, base+1) t.Errorf("#%d: n = %d, rev = %d, want (%d, %d)", i, n, rev, 1, base+1)
} }
kvs, rev, err = s.TxnRange(id, []byte("foo"), nil, 0, base+1) r, err = s.TxnRange(id, []byte("foo"), nil, RangeOptions{Rev: base + 1})
if err != nil { if err != nil {
t.Errorf("#%d: range error (%v)", i, err) t.Errorf("#%d: range error (%v)", i, err)
} }
if kvs != nil { if r.KVs != nil {
t.Errorf("#%d: kvs = %+v, want %+v", i, kvs, nil) t.Errorf("#%d: kvs = %+v, want %+v", i, r.KVs, nil)
} }
if rev != base+1 { if r.Rev != base+1 {
t.Errorf("#%d: range rev = %d, want %d", i, rev, base+1) t.Errorf("#%d: range rev = %d, want %d", i, r.Rev, base+1)
} }
s.TxnEnd(id) s.TxnEnd(id)
@ -572,12 +572,12 @@ func TestKVCompactReserveLastValue(t *testing.T) {
if err != nil { if err != nil {
t.Errorf("#%d: unexpect compact error %v", i, err) t.Errorf("#%d: unexpect compact error %v", i, err)
} }
kvs, _, err := s.Range([]byte("foo"), nil, 0, tt.rev+1) r, err := s.Range([]byte("foo"), nil, RangeOptions{Rev: tt.rev + 1})
if err != nil { if err != nil {
t.Errorf("#%d: unexpect range error %v", i, err) t.Errorf("#%d: unexpect range error %v", i, err)
} }
if !reflect.DeepEqual(kvs, tt.wkvs) { if !reflect.DeepEqual(r.KVs, tt.wkvs) {
t.Errorf("#%d: kvs = %+v, want %+v", i, kvs, tt.wkvs) t.Errorf("#%d: kvs = %+v, want %+v", i, r.KVs, tt.wkvs)
} }
} }
} }
@ -658,8 +658,8 @@ func TestKVRestore(t *testing.T) {
tt(s) tt(s)
var kvss [][]mvccpb.KeyValue var kvss [][]mvccpb.KeyValue
for k := int64(0); k < 10; k++ { for k := int64(0); k < 10; k++ {
kvs, _, _ := s.Range([]byte("a"), []byte("z"), 0, k) r, _ := s.Range([]byte("a"), []byte("z"), RangeOptions{Rev: k})
kvss = append(kvss, kvs) kvss = append(kvss, r.KVs)
} }
s.Close() s.Close()
@ -669,8 +669,8 @@ func TestKVRestore(t *testing.T) {
testutil.WaitSchedule() testutil.WaitSchedule()
var nkvss [][]mvccpb.KeyValue var nkvss [][]mvccpb.KeyValue
for k := int64(0); k < 10; k++ { for k := int64(0); k < 10; k++ {
nkvs, _, _ := ns.Range([]byte("a"), []byte("z"), 0, k) r, _ := ns.Range([]byte("a"), []byte("z"), RangeOptions{Rev: k})
nkvss = append(nkvss, nkvs) nkvss = append(nkvss, r.KVs)
} }
cleanup(ns, b, tmpPath) cleanup(ns, b, tmpPath)
@ -704,15 +704,15 @@ func TestKVSnapshot(t *testing.T) {
ns := NewStore(b, &lease.FakeLessor{}, nil) ns := NewStore(b, &lease.FakeLessor{}, nil)
defer ns.Close() defer ns.Close()
kvs, rev, err := ns.Range([]byte("a"), []byte("z"), 0, 0) r, err := ns.Range([]byte("a"), []byte("z"), RangeOptions{})
if err != nil { if err != nil {
t.Errorf("unexpect range error (%v)", err) t.Errorf("unexpect range error (%v)", err)
} }
if !reflect.DeepEqual(kvs, wkvs) { if !reflect.DeepEqual(r.KVs, wkvs) {
t.Errorf("kvs = %+v, want %+v", kvs, wkvs) t.Errorf("kvs = %+v, want %+v", r.KVs, wkvs)
} }
if rev != 4 { if r.Rev != 4 {
t.Errorf("rev = %d, want %d", rev, 4) t.Errorf("rev = %d, want %d", r.Rev, 4)
} }
} }

View File

@ -149,14 +149,20 @@ func (s *store) Put(key, value []byte, lease lease.LeaseID) int64 {
return int64(s.currentRev.main) return int64(s.currentRev.main)
} }
func (s *store) Range(key, end []byte, limit, rangeRev int64) (kvs []mvccpb.KeyValue, rev int64, err error) { func (s *store) Range(key, end []byte, ro RangeOptions) (r *RangeResult, err error) {
id := s.TxnBegin() id := s.TxnBegin()
kvs, rev, err = s.rangeKeys(key, end, limit, rangeRev) kvs, count, rev, err := s.rangeKeys(key, end, ro.Limit, ro.Rev, ro.Count)
s.txnEnd(id) s.txnEnd(id)
rangeCounter.Inc() rangeCounter.Inc()
return kvs, rev, err r = &RangeResult{
KVs: kvs,
Count: count,
Rev: rev,
}
return r, err
} }
func (s *store) DeleteRange(key, end []byte) (n, rev int64) { func (s *store) DeleteRange(key, end []byte) (n, rev int64) {
@ -208,11 +214,19 @@ func (s *store) txnEnd(txnID int64) error {
return nil return nil
} }
func (s *store) TxnRange(txnID int64, key, end []byte, limit, rangeRev int64) (kvs []mvccpb.KeyValue, rev int64, err error) { func (s *store) TxnRange(txnID int64, key, end []byte, ro RangeOptions) (r *RangeResult, err error) {
if txnID != s.txnID { if txnID != s.txnID {
return nil, 0, ErrTxnIDMismatch return nil, ErrTxnIDMismatch
} }
return s.rangeKeys(key, end, limit, rangeRev)
kvs, count, rev, err := s.rangeKeys(key, end, ro.Limit, ro.Rev, ro.Count)
r = &RangeResult{
KVs: kvs,
Count: count,
Rev: rev,
}
return r, err
} }
func (s *store) TxnPut(txnID int64, key, value []byte, lease lease.LeaseID) (rev int64, err error) { func (s *store) TxnPut(txnID int64, key, value []byte, lease lease.LeaseID) (rev int64, err error) {
@ -423,14 +437,14 @@ func (a *store) Equal(b *store) bool {
} }
// range is a keyword in Go, add Keys suffix. // range is a keyword in Go, add Keys suffix.
func (s *store) rangeKeys(key, end []byte, limit, rangeRev int64) (kvs []mvccpb.KeyValue, curRev int64, err error) { func (s *store) rangeKeys(key, end []byte, limit, rangeRev int64, countOnly bool) (kvs []mvccpb.KeyValue, count int, curRev int64, err error) {
curRev = int64(s.currentRev.main) curRev = int64(s.currentRev.main)
if s.currentRev.sub > 0 { if s.currentRev.sub > 0 {
curRev += 1 curRev += 1
} }
if rangeRev > curRev { if rangeRev > curRev {
return nil, s.currentRev.main, ErrFutureRev return nil, -1, s.currentRev.main, ErrFutureRev
} }
var rev int64 var rev int64
if rangeRev <= 0 { if rangeRev <= 0 {
@ -439,12 +453,15 @@ func (s *store) rangeKeys(key, end []byte, limit, rangeRev int64) (kvs []mvccpb.
rev = rangeRev rev = rangeRev
} }
if rev < s.compactMainRev { if rev < s.compactMainRev {
return nil, 0, ErrCompacted return nil, -1, 0, ErrCompacted
} }
_, revpairs := s.kvindex.Range(key, end, int64(rev)) _, revpairs := s.kvindex.Range(key, end, int64(rev))
if len(revpairs) == 0 { if len(revpairs) == 0 {
return nil, curRev, nil return nil, 0, curRev, nil
}
if countOnly {
return nil, len(revpairs), curRev, nil
} }
for _, revpair := range revpairs { for _, revpair := range revpairs {
@ -464,7 +481,7 @@ func (s *store) rangeKeys(key, end []byte, limit, rangeRev int64) (kvs []mvccpb.
break break
} }
} }
return kvs, curRev, nil return kvs, len(kvs), curRev, nil
} }
func (s *store) put(key, value []byte, leaseID lease.LeaseID) { func (s *store) put(key, value []byte, leaseID lease.LeaseID) {

View File

@ -206,7 +206,7 @@ func TestStoreRange(t *testing.T) {
b.tx.rangeRespc <- tt.r b.tx.rangeRespc <- tt.r
fi.indexRangeRespc <- tt.idxr fi.indexRangeRespc <- tt.idxr
kvs, rev, err := s.rangeKeys([]byte("foo"), []byte("goo"), 1, 0) kvs, _, rev, err := s.rangeKeys([]byte("foo"), []byte("goo"), 1, 0, false)
if err != nil { if err != nil {
t.Errorf("#%d: err = %v, want nil", i, err) t.Errorf("#%d: err = %v, want nil", i, err)
} }
@ -440,7 +440,7 @@ func TestRestoreContinueUnfinishedCompaction(t *testing.T) {
// wait for scheduled compaction to be finished // wait for scheduled compaction to be finished
time.Sleep(100 * time.Millisecond) time.Sleep(100 * time.Millisecond)
if _, _, err := s1.Range([]byte("foo"), nil, 0, 1); err != ErrCompacted { if _, err := s1.Range([]byte("foo"), nil, RangeOptions{Rev: 1}); err != ErrCompacted {
t.Errorf("range on compacted rev error = %v, want %v", err, ErrCompacted) t.Errorf("range on compacted rev error = %v, want %v", err, ErrCompacted)
} }
// check the key in backend is deleted // check the key in backend is deleted