Browse Source

Merge pull request #5742 from xiang90/count

*: support count in range query
Xiang Li 9 years ago
parent
commit
0b5ea3ec94

+ 11 - 1
Documentation/dev-guide/apispec/swagger/rpc.swagger.json

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

+ 28 - 19
etcdserver/apply.go

@@ -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
-		rev int64
+		rr  *mvcc.RangeResult
 		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) {
-		kvs = kvs[:r.Limit]
+	if r.Limit > 0 && len(rr.KVs) > int(r.Limit) {
+		rr.KVs = rr.KVs[:r.Limit]
 		resp.More = true
 		resp.More = true
 	}
 	}
 
 
-	resp.Header.Revision = rev
-	for i := range kvs {
+	resp.Header.Revision = rr.Rev
+	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 {
-		ckv = ckvs[0]
+	if len(rr.KVs) != 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
 }
 }
 
 

+ 260 - 194
etcdserver/etcdserverpb/rpc.pb.go

@@ -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,
-	0xda, 0xa7, 0x5f, 0x9a, 0xbf, 0x65, 0xff, 0x39, 0x00, 0xe1, 0x88, 0x91, 0x66, 0x58, 0xcb, 0x92,
-	0xa5, 0x75, 0x6b, 0x56, 0x36, 0x11, 0x04, 0x8a, 0xd6, 0x4c, 0xad, 0x34, 0xa1, 0x79, 0xb9, 0xbb,
-	0x47, 0x2b, 0x19, 0x1c, 0x41, 0x38, 0xf0, 0x01, 0xae, 0x3e, 0x10, 0xc0, 0x91, 0x4f, 0xc0, 0x81,
-	0x1b, 0x1f, 0x80, 0xe0, 0x02, 0x11, 0x1c, 0xb9, 0x10, 0x04, 0x07, 0x0e, 0xdc, 0x09, 0x4e, 0x50,
-	0xcf, 0xee, 0xea, 0x9e, 0xea, 0x91, 0x4c, 0xe3, 0xc3, 0xae, 0xba, 0xb2, 0xb2, 0xf2, 0x97, 0x95,
-	0x55, 0x99, 0x9d, 0x99, 0x3d, 0x50, 0x70, 0x87, 0xad, 0xb5, 0xa1, 0x3b, 0xf0, 0x07, 0xa8, 0x44,
-	0xfc, 0x56, 0xdb, 0x23, 0xee, 0x19, 0x71, 0x87, 0x47, 0xd6, 0xe2, 0xf1, 0xe0, 0x78, 0xc0, 0x27,
-	0xaa, 0xec, 0x49, 0xf0, 0x58, 0x4b, 0x8c, 0xa7, 0xda, 0x3b, 0x6b, 0xb5, 0xf8, 0x7f, 0xc3, 0xa3,
-	0xea, 0xe9, 0x99, 0x9c, 0xba, 0xcd, 0xa7, 0x9c, 0x91, 0x7f, 0xc2, 0xff, 0xa3, 0x53, 0xec, 0x8f,
-	0x9c, 0x5c, 0x3e, 0x1e, 0x0c, 0x8e, 0xbb, 0xa4, 0xea, 0x0c, 0x3b, 0x55, 0xa7, 0xdf, 0x1f, 0xf8,
-	0x8e, 0xdf, 0x19, 0xf4, 0x3d, 0x31, 0x8b, 0xbf, 0xc8, 0x40, 0xd9, 0x26, 0xde, 0x90, 0x52, 0xc8,
-	0x7b, 0xc4, 0x69, 0x13, 0x17, 0xdd, 0x01, 0x68, 0x75, 0x47, 0x9e, 0x4f, 0xdc, 0xc3, 0x4e, 0xbb,
-	0x92, 0x59, 0xcd, 0x3c, 0xc9, 0xdb, 0x05, 0x49, 0xd9, 0x6a, 0xa3, 0xdb, 0x50, 0xe8, 0x91, 0xde,
-	0x91, 0x98, 0xcd, 0xf2, 0xd9, 0x59, 0x41, 0xa0, 0x93, 0x16, 0xcc, 0xba, 0xe4, 0xac, 0xe3, 0x51,
-	0x84, 0x4a, 0x8e, 0xce, 0xe5, 0xec, 0x60, 0xcc, 0x16, 0xba, 0xce, 0x0b, 0xff, 0x90, 0x8a, 0xe9,
-	0x55, 0xf2, 0x62, 0x21, 0x23, 0x34, 0xe9, 0x18, 0xff, 0x3a, 0x07, 0x25, 0xdb, 0xe9, 0x1f, 0x13,
-	0x9b, 0x7c, 0x32, 0x22, 0x9e, 0x8f, 0xe6, 0x21, 0x77, 0x4a, 0x2e, 0x38, 0x7c, 0xc9, 0x66, 0x8f,
-	0x62, 0x3d, 0xe5, 0x38, 0x24, 0x7d, 0x01, 0x5c, 0x62, 0xeb, 0x29, 0xa1, 0xd1, 0x6f, 0xa3, 0x45,
-	0x98, 0xea, 0x76, 0x7a, 0x1d, 0x5f, 0xa2, 0x8a, 0x41, 0x44, 0x9d, 0x7c, 0x4c, 0x9d, 0x4d, 0x00,
-	0x6f, 0xe0, 0xfa, 0x87, 0x03, 0x97, 0x6e, 0xba, 0x32, 0x45, 0x67, 0xcb, 0xeb, 0x0f, 0xd6, 0xf4,
-	0x83, 0x58, 0xd3, 0x15, 0x5a, 0xdb, 0xa7, 0xcc, 0x7b, 0x8c, 0xd7, 0x2e, 0x78, 0xea, 0x11, 0x7d,
-	0x07, 0x8a, 0x5c, 0x88, 0xef, 0xb8, 0xc7, 0xc4, 0xaf, 0x4c, 0x73, 0x29, 0x0f, 0x2f, 0x91, 0xd2,
-	0xe4, 0xcc, 0x36, 0x87, 0x17, 0xcf, 0x08, 0x43, 0x89, 0xf2, 0x77, 0x9c, 0x6e, 0xe7, 0x53, 0xe7,
-	0xa8, 0x4b, 0x2a, 0x33, 0x54, 0xd0, 0xac, 0x1d, 0xa1, 0xb1, 0xfd, 0x53, 0x33, 0x78, 0x87, 0x83,
-	0x7e, 0xf7, 0xa2, 0x32, 0xcb, 0x19, 0x66, 0x19, 0x61, 0x8f, 0x8e, 0xf1, 0x1a, 0x14, 0x02, 0x05,
-	0xd1, 0x2c, 0xe4, 0x77, 0xf7, 0x76, 0x1b, 0xf3, 0xd7, 0x10, 0xc0, 0x74, 0x6d, 0x7f, 0xb3, 0xb1,
-	0x5b, 0x9f, 0xcf, 0xa0, 0x22, 0xcc, 0xd4, 0x1b, 0x62, 0x90, 0xc5, 0x1b, 0x00, 0xa1, 0x2a, 0x68,
-	0x06, 0x72, 0xdb, 0x8d, 0xef, 0x52, 0x7e, 0xca, 0x73, 0xd0, 0xb0, 0xf7, 0xb7, 0xf6, 0x76, 0xe9,
-	0x02, 0xba, 0x78, 0xd3, 0x6e, 0xd4, 0x9a, 0x8d, 0xf9, 0x2c, 0xe3, 0xf8, 0x60, 0xaf, 0x3e, 0x9f,
-	0x43, 0x05, 0x98, 0x3a, 0xa8, 0xed, 0x3c, 0x6f, 0xcc, 0xe7, 0xf1, 0x67, 0x30, 0x27, 0xf7, 0x26,
-	0xee, 0x0f, 0x7a, 0x07, 0xa6, 0x4f, 0xf8, 0x1d, 0xe2, 0xc7, 0x56, 0x5c, 0x5f, 0x8e, 0x19, 0x22,
-	0x72, 0xcf, 0x6c, 0xc9, 0x4b, 0xf7, 0x9e, 0x3b, 0x3d, 0xf3, 0xe8, 0x89, 0xe6, 0xe8, 0x92, 0xf9,
-	0x35, 0x71, 0xb9, 0xd7, 0xb6, 0xc9, 0xc5, 0x81, 0xd3, 0x1d, 0x11, 0x9b, 0x4d, 0x22, 0x04, 0xf9,
-	0xde, 0xc0, 0x25, 0xfc, 0x74, 0x67, 0x6d, 0xfe, 0x8c, 0xdf, 0x07, 0x78, 0x36, 0xf2, 0x93, 0xef,
-	0x0b, 0xbd, 0x12, 0x67, 0x4c, 0x82, 0xbc, 0x2b, 0x62, 0xc0, 0x2f, 0x0a, 0x71, 0x3c, 0x12, 0x5c,
-	0x14, 0x36, 0xc0, 0x9b, 0x50, 0xe4, 0xb2, 0xd2, 0x6c, 0x84, 0x0a, 0x41, 0x75, 0xd2, 0x25, 0x3e,
-	0x49, 0x71, 0x91, 0x31, 0x81, 0x85, 0x88, 0x90, 0x54, 0xa6, 0xad, 0xc0, 0x4c, 0x9b, 0x0b, 0x13,
-	0x38, 0x39, 0x5b, 0x0d, 0xf1, 0x3f, 0x32, 0x50, 0x90, 0x1a, 0xee, 0x0d, 0x51, 0x0d, 0xe6, 0x5c,
-	0x31, 0x38, 0xe4, 0x8a, 0x48, 0x10, 0x2b, 0xf9, 0x22, 0xbf, 0x77, 0xcd, 0x2e, 0xc9, 0x25, 0x9c,
-	0x8c, 0xbe, 0x05, 0x45, 0x25, 0x62, 0x38, 0xf2, 0x39, 0x5c, 0x71, 0xbd, 0x12, 0x15, 0x10, 0x1e,
-	0x17, 0x5d, 0x0e, 0x92, 0x9d, 0x12, 0x51, 0x13, 0x16, 0xd5, 0x62, 0xa1, 0xa0, 0x54, 0x23, 0xc7,
-	0xa5, 0xac, 0x46, 0xa5, 0x8c, 0xdb, 0x98, 0x4a, 0x43, 0x72, 0xbd, 0x36, 0xb9, 0x51, 0x80, 0x19,
-	0x49, 0xc5, 0xff, 0xcc, 0x00, 0x28, 0x1b, 0xd1, 0xfd, 0xd6, 0xa1, 0xec, 0xca, 0x51, 0x64, 0xc3,
-	0xb7, 0x8d, 0x1b, 0x96, 0xa6, 0xbd, 0x66, 0xcf, 0xa9, 0x45, 0x62, 0xcb, 0xef, 0x42, 0x29, 0x90,
-	0x12, 0xee, 0x79, 0xc9, 0xb0, 0xe7, 0x40, 0x42, 0x51, 0x2d, 0x60, 0xbb, 0xfe, 0x08, 0x6e, 0x06,
-	0xeb, 0x0d, 0xdb, 0xbe, 0x37, 0x61, 0xdb, 0x81, 0xc0, 0x05, 0x25, 0x41, 0xdf, 0x38, 0xb0, 0xb0,
-	0x27, 0xc8, 0xf8, 0x17, 0x39, 0x98, 0xd9, 0x1c, 0xf4, 0x86, 0x8e, 0xcb, 0xce, 0x68, 0x9a, 0xd2,
-	0x47, 0x5d, 0x9f, 0x6f, 0xb7, 0xbc, 0x7e, 0x3f, 0x8a, 0x20, 0xd9, 0xd4, 0x5f, 0x9b, 0xb3, 0xda,
-	0x72, 0x09, 0x5b, 0x2c, 0xa3, 0x5c, 0xf6, 0x0a, 0x8b, 0x65, 0x8c, 0x93, 0x4b, 0x94, 0x13, 0xe4,
-	0x42, 0x27, 0xb0, 0x60, 0x86, 0x2e, 0x0c, 0x23, 0x33, 0xdd, 0x8b, 0x22, 0xa0, 0x57, 0xe1, 0x7a,
-	0xcb, 0x25, 0x0e, 0xb3, 0x87, 0x8a, 0xde, 0x53, 0x92, 0xa7, 0x2c, 0x26, 0x6c, 0x15, 0xc5, 0xef,
-	0x43, 0xa9, 0x37, 0x68, 0x87, 0x7c, 0xd3, 0x92, 0xaf, 0x48, 0xa9, 0x01, 0xd3, 0x2d, 0x15, 0x09,
-	0x58, 0x58, 0x2d, 0xd1, 0x59, 0x31, 0xc4, 0x6f, 0xc1, 0x5c, 0x64, 0xaf, 0x2c, 0xb8, 0x35, 0x3e,
-	0x7c, 0x5e, 0xdb, 0x11, 0x91, 0xf0, 0x29, 0x0f, 0x7e, 0x36, 0x8d, 0x84, 0x34, 0xa0, 0xee, 0x34,
-	0xf6, 0xf7, 0x69, 0xdc, 0xfc, 0x76, 0xb0, 0x44, 0x86, 0x4e, 0x2d, 0x62, 0x5e, 0xd3, 0x22, 0x66,
-	0x46, 0x45, 0xcc, 0x6c, 0x18, 0x31, 0x73, 0x1b, 0x65, 0x28, 0x09, 0x83, 0x1c, 0x8e, 0xfa, 0x54,
-	0x31, 0xfc, 0x2b, 0x7a, 0x2d, 0x9b, 0xe7, 0x7d, 0x15, 0x2a, 0xaa, 0x30, 0xd3, 0x12, 0xc2, 0xe9,
-	0x01, 0xb1, 0x68, 0x78, 0xd3, 0x68, 0x63, 0x5b, 0x71, 0xa1, 0xb7, 0x60, 0xc6, 0x1b, 0xb5, 0x5a,
-	0xc4, 0x53, 0xe1, 0xf3, 0x95, 0x78, 0x58, 0x90, 0x1e, 0x6e, 0x2b, 0x3e, 0xb6, 0xe4, 0x85, 0xd3,
-	0xe9, 0x8e, 0x78, 0x30, 0x9d, 0xbc, 0x44, 0xf2, 0xe1, 0x9f, 0x67, 0xa0, 0xc8, 0xb5, 0x4c, 0x15,
-	0x8b, 0x96, 0xa1, 0xc0, 0x75, 0x20, 0x6d, 0x19, 0x8d, 0x66, 0xed, 0x90, 0x80, 0xbe, 0x41, 0x63,
-	0xa2, 0x5c, 0xe7, 0x49, 0xc5, 0x2a, 0x66, 0xb1, 0x54, 0xb3, 0x90, 0x15, 0x6f, 0xc3, 0x0d, 0x6e,
-	0x95, 0x16, 0x4b, 0x6a, 0x94, 0x1d, 0xf5, 0xd7, 0x7e, 0x26, 0xf6, 0xda, 0xa7, 0x73, 0xc3, 0x93,
-	0x0b, 0xaf, 0xd3, 0x72, 0xba, 0x52, 0x8b, 0x60, 0x4c, 0xdf, 0x28, 0x48, 0x17, 0x96, 0xea, 0x65,
-	0x30, 0x07, 0xc5, 0xf7, 0x1c, 0xef, 0x44, 0xaa, 0x84, 0x3f, 0x86, 0x92, 0x18, 0xa6, 0xb2, 0x21,
-	0x7d, 0x0d, 0x9e, 0x50, 0x29, 0x5c, 0xf1, 0x39, 0x9b, 0x3f, 0xe3, 0x1b, 0x70, 0x7d, 0xbf, 0xef,
-	0x0c, 0xbd, 0x93, 0x81, 0x0a, 0xae, 0x2c, 0xa9, 0x9b, 0x0f, 0x69, 0xa9, 0x10, 0x1f, 0xc3, 0x75,
-	0x97, 0xf4, 0x9c, 0x4e, 0xbf, 0xd3, 0x3f, 0x3e, 0x3c, 0xba, 0xf0, 0x89, 0x27, 0x73, 0xbe, 0x72,
-	0x40, 0xde, 0x60, 0x54, 0xa6, 0xda, 0x51, 0x77, 0x70, 0x24, 0x5d, 0x9c, 0x3f, 0xe3, 0xdf, 0x64,
-	0xa0, 0xf4, 0x91, 0xe3, 0xb7, 0x94, 0x15, 0xd0, 0x16, 0x94, 0x03, 0xc7, 0xe6, 0x14, 0xa9, 0x4b,
-	0x2c, 0xc2, 0xf3, 0x35, 0x9b, 0xd2, 0xd1, 0x55, 0x84, 0x9f, 0x6b, 0xe9, 0x04, 0x2e, 0xca, 0xe9,
-	0xb7, 0x48, 0x37, 0x10, 0x95, 0x4d, 0x16, 0xc5, 0x19, 0x75, 0x51, 0x3a, 0x61, 0xe3, 0x7a, 0xf8,
-	0xf6, 0x13, 0x6e, 0xf9, 0x65, 0x06, 0xd0, 0xb8, 0x0e, 0x5f, 0x35, 0x25, 0x7d, 0x08, 0x65, 0x8f,
-	0x7a, 0xbb, 0x7f, 0x18, 0xcb, 0x88, 0xe7, 0x38, 0x35, 0x08, 0x4e, 0xd4, 0xc2, 0x34, 0x15, 0x3f,
-	0xa6, 0x57, 0xda, 0x3b, 0xa4, 0xd9, 0x79, 0xe7, 0xc5, 0x05, 0x0f, 0x88, 0xb3, 0x76, 0x59, 0x91,
-	0x77, 0x39, 0x15, 0x57, 0x95, 0x52, 0xba, 0xf2, 0x68, 0x09, 0x66, 0x5f, 0x32, 0xaa, 0xca, 0xd5,
-	0xe9, 0x3b, 0x9e, 0x8f, 0xb7, 0xda, 0xf8, 0xef, 0x19, 0x98, 0x93, 0xe6, 0x4f, 0x75, 0x07, 0x74,
-	0x88, 0x6c, 0x04, 0x82, 0x25, 0x18, 0xe2, 0x58, 0xda, 0x32, 0x35, 0x53, 0x43, 0xe6, 0x67, 0xc2,
-	0xca, 0x74, 0x4a, 0xec, 0x27, 0x18, 0xd3, 0xf8, 0x3e, 0xdf, 0x12, 0x7e, 0x16, 0x0b, 0xf0, 0xf6,
-	0x75, 0x49, 0x0f, 0xac, 0xf3, 0x10, 0xa6, 0xc9, 0x19, 0xe9, 0xfb, 0x5e, 0xa5, 0xc8, 0x83, 0xc2,
-	0x9c, 0xca, 0x0f, 0x1b, 0x8c, 0x6a, 0xcb, 0x49, 0xfc, 0xff, 0x70, 0x63, 0x87, 0x25, 0x72, 0x4f,
-	0xa9, 0xf5, 0xf5, 0x94, 0xb0, 0xd9, 0xdc, 0x91, 0x56, 0xc9, 0xf9, 0xcd, 0x1d, 0x54, 0x86, 0xec,
-	0x56, 0x5d, 0xee, 0x21, 0xdb, 0xa9, 0xe3, 0xcf, 0xe9, 0x41, 0xeb, 0xeb, 0x52, 0x99, 0x29, 0x26,
-	0x5c, 0xc1, 0xe7, 0x42, 0x78, 0x9a, 0x7b, 0x12, 0xd7, 0x1d, 0xb8, 0xdc, 0x20, 0x05, 0x5b, 0x0c,
-	0xf0, 0x03, 0xa9, 0x03, 0xdd, 0xf3, 0xe0, 0x34, 0xb8, 0x6c, 0x42, 0x5a, 0x26, 0x50, 0x75, 0x1b,
-	0x16, 0x22, 0x5c, 0xa9, 0x82, 0xd3, 0x63, 0xb8, 0xc9, 0x85, 0x6d, 0x13, 0x32, 0xac, 0x75, 0x3b,
-	0x67, 0x89, 0xa8, 0x43, 0xb8, 0x15, 0x67, 0xfc, 0x7a, 0x6d, 0x84, 0x4f, 0x60, 0xfa, 0x03, 0x5e,
-	0x4d, 0x6a, 0xba, 0xe4, 0x39, 0x2f, 0x8d, 0x30, 0x7d, 0xa7, 0x27, 0xd2, 0xf9, 0x82, 0xcd, 0x9f,
-	0x79, 0x34, 0x27, 0xc4, 0x7d, 0x6e, 0xef, 0x88, 0xb7, 0x46, 0xc1, 0x0e, 0xc6, 0x68, 0x85, 0xd5,
-	0xb1, 0x1d, 0x7a, 0x3d, 0xf8, 0x6c, 0x9e, 0xcf, 0x6a, 0x14, 0x5a, 0x32, 0xcd, 0x0b, 0xa4, 0x5a,
-	0xbb, 0xad, 0xbd, 0x39, 0x02, 0x79, 0x99, 0xa8, 0x3c, 0xfc, 0x12, 0x6e, 0x68, 0xfc, 0xa9, 0xcc,
-	0xf0, 0x06, 0x4c, 0x8b, 0x92, 0x59, 0x06, 0xad, 0xc5, 0xe8, 0x2a, 0x01, 0x63, 0x4b, 0x1e, 0xfc,
-	0x10, 0x16, 0x24, 0x85, 0xf4, 0x06, 0xa6, 0xb3, 0xe2, 0xf6, 0xc1, 0x3b, 0xb0, 0x18, 0x65, 0x4b,
-	0x75, 0x45, 0x6a, 0x0a, 0xf4, 0xf9, 0xb0, 0xad, 0xc5, 0xc0, 0xf8, 0xa1, 0xe8, 0x06, 0xcb, 0xc6,
-	0x0c, 0x16, 0x28, 0xa4, 0x44, 0xa4, 0x52, 0x68, 0x41, 0x99, 0x7f, 0xa7, 0xe3, 0x05, 0x6f, 0xba,
-	0x4f, 0x01, 0xe9, 0xc4, 0x54, 0x87, 0xb2, 0x06, 0x33, 0xc2, 0xe0, 0x2a, 0x99, 0x32, 0x9f, 0x8a,
-	0x62, 0x62, 0x0a, 0xd5, 0xc9, 0x0b, 0xd7, 0x39, 0xee, 0x91, 0x20, 0xe6, 0xb0, 0x14, 0x42, 0x27,
-	0xa6, 0xda, 0xf1, 0x1f, 0xe8, 0xeb, 0xb3, 0xd6, 0x75, 0xdc, 0x9e, 0x32, 0xfe, 0xbb, 0x30, 0x2d,
-	0x72, 0x13, 0x99, 0xbf, 0x3f, 0x8a, 0x8a, 0xd1, 0x79, 0xc5, 0xa0, 0x26, 0x32, 0x19, 0xb9, 0x8a,
-	0x1d, 0x96, 0xec, 0xd4, 0xd4, 0x63, 0x9d, 0x9b, 0x3a, 0x7a, 0x13, 0xa6, 0x1c, 0xb6, 0x84, 0xfb,
-	0x62, 0x39, 0x9e, 0x15, 0x72, 0x69, 0xcd, 0x8b, 0x21, 0xb1, 0x05, 0x17, 0x7e, 0x07, 0x8a, 0x1a,
-	0x02, 0x4b, 0x76, 0x9f, 0x36, 0x9a, 0x34, 0x03, 0x2e, 0xc1, 0x6c, 0x6d, 0xb3, 0xb9, 0x75, 0x20,
-	0x72, 0xe0, 0x32, 0x40, 0xbd, 0x11, 0x8c, 0xb3, 0x34, 0x0b, 0x12, 0xab, 0xa4, 0x87, 0xeb, 0xfa,
-	0x64, 0x92, 0xf4, 0xc9, 0x5e, 0x49, 0x9f, 0x73, 0x98, 0x93, 0xdb, 0x4f, 0x75, 0x07, 0xde, 0xa2,
-	0x16, 0x66, 0x62, 0xd4, 0x15, 0x58, 0x32, 0xc0, 0x2a, 0xef, 0x14, 0x8c, 0x98, 0x66, 0x0f, 0xfb,
-	0xbe, 0xe3, 0x8f, 0x3c, 0x75, 0x05, 0x7e, 0x9f, 0x81, 0xb2, 0xa2, 0xa4, 0xad, 0xde, 0x55, 0x89,
-	0x24, 0x62, 0x5e, 0x50, 0x20, 0xdd, 0x82, 0xe9, 0xf6, 0xd1, 0x7e, 0xe7, 0x53, 0xd5, 0xc5, 0x90,
-	0x23, 0x46, 0xef, 0x0a, 0x1c, 0xd1, 0x5f, 0x93, 0x23, 0x96, 0x7b, 0xb3, 0x4e, 0xdb, 0x56, 0xbf,
-	0x4d, 0xce, 0xf9, 0x9b, 0x36, 0x6f, 0x87, 0x04, 0x9e, 0x2e, 0xcb, 0x3e, 0x1c, 0xaf, 0x9f, 0xf4,
-	0xbe, 0x1c, 0xbd, 0xe4, 0xb5, 0x91, 0x7f, 0xd2, 0xe8, 0xb3, 0x16, 0x94, 0xda, 0xe1, 0x22, 0x20,
-	0x46, 0xac, 0x77, 0x3c, 0x9d, 0xda, 0x80, 0x05, 0x46, 0xa5, 0xf7, 0x9e, 0x26, 0xd3, 0x61, 0xc4,
-	0x50, 0x61, 0x3b, 0x13, 0x0b, 0xdb, 0x8e, 0xe7, 0xbd, 0x1c, 0xb8, 0x6d, 0xb9, 0xb5, 0x60, 0x8c,
-	0xeb, 0x42, 0xf8, 0x73, 0x2f, 0x12, 0x98, 0xbf, 0xaa, 0x94, 0x27, 0xa1, 0x94, 0xa7, 0xc4, 0x9f,
-	0x20, 0x05, 0xbf, 0x0e, 0x37, 0x15, 0xa7, 0xac, 0xa1, 0x27, 0x30, 0xef, 0xc1, 0x1d, 0xc5, 0xbc,
-	0x79, 0xc2, 0x12, 0xbd, 0x67, 0x12, 0xf0, 0xbf, 0xd5, 0x73, 0x03, 0x2a, 0x81, 0x9e, 0x3c, 0x07,
-	0x19, 0x74, 0x75, 0x05, 0x46, 0x9e, 0xbc, 0x33, 0x54, 0x16, 0x7b, 0x66, 0x34, 0x97, 0xb2, 0xa8,
-	0x97, 0x20, 0x7b, 0xc6, 0x9b, 0xb0, 0xa4, 0x64, 0xc8, 0xec, 0x20, 0x2a, 0x64, 0x4c, 0x21, 0x93,
-	0x10, 0x69, 0x30, 0xb6, 0x74, 0xb2, 0xd9, 0x75, 0xce, 0xa8, 0x69, 0xb9, 0xcc, 0x8c, 0x26, 0xf3,
-	0xa6, 0xb8, 0x11, 0x4c, 0x31, 0x3d, 0x68, 0x4b, 0x32, 0x13, 0xa0, 0x93, 0xe5, 0x41, 0x30, 0xf2,
-	0xd8, 0x41, 0x8c, 0x89, 0xfe, 0x1e, 0xac, 0x04, 0x4a, 0x30, 0xbb, 0x3d, 0xa3, 0x97, 0xb5, 0xe3,
-	0x79, 0x5a, 0x11, 0x68, 0xda, 0xf8, 0x23, 0xc8, 0x0f, 0x89, 0x8c, 0x29, 0xc5, 0x75, 0xb4, 0x26,
-	0xba, 0xe5, 0x6b, 0xda, 0x62, 0x3e, 0x8f, 0xdb, 0x70, 0x57, 0x49, 0x17, 0x16, 0x35, 0x8a, 0x8f,
-	0x2b, 0xa5, 0x0a, 0x04, 0x61, 0xd6, 0xf1, 0x02, 0x21, 0x27, 0xce, 0x3e, 0x68, 0xf5, 0xbd, 0x2f,
-	0x0c, 0xa9, 0x7c, 0x2b, 0xd5, 0xbb, 0x62, 0x5b, 0xd8, 0x34, 0x70, 0xc9, 0x54, 0xc2, 0x8e, 0x60,
-	0x31, 0xea, 0xc9, 0xa9, 0xc2, 0x18, 0xcd, 0x7a, 0x7d, 0x6a, 0x42, 0x15, 0xc4, 0xc4, 0x40, 0x29,
-	0x1c, 0xb8, 0x79, 0x2a, 0x85, 0x9d, 0x50, 0x18, 0xbf, 0x92, 0x69, 0xf5, 0x65, 0xa7, 0xa9, 0xf2,
-	0x19, 0x31, 0xc0, 0xbb, 0x70, 0x2b, 0x1e, 0x26, 0x52, 0xa9, 0x7c, 0x20, 0x2e, 0xb0, 0x29, 0x92,
-	0xa4, 0x92, 0xfb, 0x61, 0x18, 0x0c, 0xb4, 0x80, 0x92, 0x4a, 0xa4, 0x0d, 0x96, 0x29, 0xbe, 0xfc,
-	0x2f, 0xee, 0x6b, 0x10, 0x6e, 0x52, 0x09, 0xf3, 0x42, 0x61, 0xe9, 0x8f, 0x3f, 0x8c, 0x11, 0xb9,
-	0x89, 0x31, 0x42, 0x3a, 0x49, 0x18, 0xc5, 0xbe, 0x86, 0x4b, 0x27, 0x31, 0xc2, 0x00, 0x9a, 0x16,
-	0x83, 0xbd, 0x43, 0x02, 0x0c, 0x3e, 0x50, 0x17, 0x5b, 0x0f, 0xbb, 0xa9, 0x0e, 0xe3, 0xa3, 0x30,
-	0x76, 0x8e, 0x45, 0xe6, 0x54, 0x82, 0x3f, 0x86, 0xd5, 0xe4, 0xa0, 0x9c, 0x46, 0xf2, 0x6b, 0x18,
-	0x0a, 0x41, 0x42, 0xa9, 0x7d, 0x3c, 0x2b, 0xc2, 0xcc, 0xee, 0xde, 0xfe, 0xb3, 0xda, 0x26, 0x4d,
-	0x65, 0xd7, 0xff, 0x9c, 0x83, 0xec, 0xf6, 0x01, 0xfa, 0x3e, 0x4c, 0x89, 0xe6, 0xff, 0x84, 0x6f,
-	0x23, 0xd6, 0xa4, 0xcf, 0x08, 0x78, 0xf9, 0xf3, 0x3f, 0xfd, 0xed, 0xcb, 0xec, 0x2d, 0x7c, 0xa3,
-	0x7a, 0xf6, 0xb6, 0xd3, 0x1d, 0x9e, 0x38, 0xd5, 0xd3, 0xb3, 0x2a, 0x7f, 0x27, 0x7c, 0x33, 0xf3,
-	0x1a, 0x3a, 0x80, 0x1c, 0xfb, 0x34, 0x90, 0xf8, 0xe1, 0xc4, 0x4a, 0xfe, 0xbc, 0x80, 0x2d, 0x2e,
-	0x79, 0x11, 0x5f, 0xd7, 0x25, 0x0f, 0x47, 0x3e, 0x93, 0xdb, 0x84, 0xa2, 0xf6, 0x85, 0x00, 0x5d,
-	0xfa, 0x49, 0xc5, 0xba, 0xfc, 0xeb, 0x03, 0xbe, 0xc6, 0xb4, 0x6d, 0x9e, 0xf7, 0xe3, 0xda, 0x86,
-	0x1d, 0xed, 0xb8, 0xb6, 0x5a, 0x17, 0xd9, 0xac, 0xad, 0x7f, 0xde, 0x67, 0xda, 0x0e, 0xe4, 0x37,
-	0x8b, 0x96, 0x8f, 0xee, 0x1a, 0x5a, 0xe0, 0x7a, 0xb3, 0xd7, 0x5a, 0x4d, 0x66, 0x90, 0x48, 0xf7,
-	0x38, 0xd2, 0x6d, 0x7c, 0x4b, 0x47, 0x6a, 0x05, 0x7c, 0x14, 0x70, 0xfd, 0x04, 0xa6, 0x78, 0xa7,
-	0x0c, 0x1d, 0xaa, 0x07, 0xcb, 0xd0, 0x47, 0x4c, 0x38, 0xdf, 0x48, 0x8f, 0x0d, 0x2f, 0x71, 0xb4,
-	0x05, 0x5c, 0x0e, 0xd0, 0x78, 0xb3, 0x8c, 0xa2, 0x3c, 0xc9, 0xfc, 0x5f, 0x66, 0xfd, 0x5f, 0x59,
-	0x98, 0xe2, 0x2d, 0x15, 0x34, 0x04, 0x08, 0x7b, 0x4f, 0xf1, 0x7d, 0x8e, 0x75, 0xb3, 0xe2, 0xfb,
-	0x1c, 0x6f, 0x5b, 0xe1, 0xbb, 0x1c, 0x79, 0x09, 0x2f, 0x06, 0xc8, 0xfc, 0xe3, 0x66, 0xf5, 0x98,
-	0x71, 0x31, 0xb3, 0xbe, 0x84, 0xa2, 0xd6, 0x43, 0x42, 0x26, 0x89, 0x91, 0x26, 0x54, 0xfc, 0x12,
-	0x18, 0x1a, 0x50, 0xf8, 0x3e, 0x07, 0xbd, 0x83, 0x2b, 0xba, 0x71, 0x05, 0xae, 0xcb, 0x39, 0x19,
-	0xf0, 0x8f, 0x69, 0x49, 0x14, 0xed, 0x23, 0xa1, 0xfb, 0x06, 0xd1, 0xf1, 0x76, 0x94, 0xf5, 0x60,
-	0x32, 0x53, 0xa2, 0x0a, 0x02, 0xff, 0x94, 0x72, 0x3a, 0x8c, 0x53, 0xd9, 0xfe, 0xdf, 0xec, 0x5b,
-	0x98, 0xf8, 0x21, 0x03, 0xf2, 0xa1, 0x10, 0x74, 0x73, 0xd0, 0x8a, 0xa9, 0xd2, 0x0f, 0xd3, 0x60,
-	0xeb, 0x6e, 0xe2, 0xbc, 0x54, 0xe1, 0x11, 0x57, 0x61, 0x15, 0xdf, 0x0e, 0x54, 0x90, 0x3f, 0x98,
-	0xa8, 0x8a, 0x82, 0xb6, 0xea, 0xb4, 0xdb, 0xcc, 0x10, 0x3f, 0xa2, 0x25, 0xbd, 0xde, 0xa4, 0x41,
-	0xf7, 0x8c, 0x3d, 0x06, 0xbd, 0xcf, 0x63, 0xe1, 0x49, 0x2c, 0x12, 0xff, 0x55, 0x8e, 0x7f, 0x1f,
-	0xaf, 0x24, 0xe1, 0xbb, 0x9c, 0x3f, 0xaa, 0x82, 0x68, 0xcb, 0x98, 0x55, 0x88, 0x74, 0x7d, 0xcc,
-	0x2a, 0x44, 0xbb, 0x3a, 0x97, 0xab, 0x30, 0xe2, 0xfc, 0x4c, 0x85, 0x73, 0x80, 0xb0, 0x6b, 0x83,
-	0x8c, 0xc6, 0xd5, 0x0a, 0x83, 0xf8, 0xcd, 0x1f, 0x6f, 0xf8, 0xe0, 0xc7, 0x1c, 0xfb, 0x1e, 0x5e,
-	0x4e, 0xc2, 0xee, 0x52, 0x6e, 0xe6, 0xe7, 0xbf, 0xcd, 0x43, 0xf1, 0x03, 0xa7, 0xd3, 0xf7, 0x49,
-	0x9f, 0x35, 0xa3, 0xd1, 0x31, 0x4c, 0xf1, 0xc8, 0x1f, 0x77, 0x77, 0xbd, 0x95, 0x12, 0x77, 0xf7,
-	0x48, 0x9f, 0x01, 0x3f, 0xe4, 0xd0, 0x77, 0xb1, 0x15, 0x40, 0xf7, 0x42, 0xf9, 0x55, 0xde, 0x23,
-	0x60, 0x5b, 0x3e, 0x85, 0x69, 0xd1, 0x13, 0x40, 0x31, 0x69, 0x91, 0xde, 0x81, 0xb5, 0x6c, 0x9e,
-	0x4c, 0xbc, 0x65, 0x3a, 0x96, 0xc7, 0x99, 0x19, 0xd8, 0x0f, 0x00, 0xc2, 0x26, 0x54, 0xdc, 0xbe,
-	0x63, 0x3d, 0x2b, 0x6b, 0x35, 0x99, 0x41, 0x02, 0xbf, 0xc6, 0x81, 0x1f, 0xe0, 0xbb, 0x46, 0xe0,
-	0x76, 0xb0, 0x80, 0x81, 0xb7, 0x20, 0xcf, 0xbe, 0x74, 0xa1, 0x58, 0xe8, 0xd7, 0x3e, 0x86, 0x59,
-	0x96, 0x69, 0x4a, 0x42, 0x3d, 0xe0, 0x50, 0x2b, 0x78, 0xc9, 0x08, 0xc5, 0xbe, 0x78, 0x31, 0x90,
-	0x11, 0xcc, 0xaa, 0x0f, 0x5c, 0xe8, 0x4e, 0xcc, 0x66, 0xd1, 0x8f, 0x61, 0xd6, 0x4a, 0xd2, 0xb4,
-	0x04, 0x7c, 0xc2, 0x01, 0x31, 0xbe, 0x63, 0x36, 0xaa, 0x64, 0xa7, 0xa0, 0x34, 0x80, 0xfc, 0x74,
-	0x1e, 0xf2, 0x2c, 0x07, 0x61, 0xb1, 0x3b, 0x2c, 0xdd, 0xe2, 0x16, 0x1e, 0x6b, 0x98, 0xc4, 0x2d,
-	0x3c, 0x5e, 0xf5, 0x19, 0x62, 0x37, 0xff, 0x39, 0x17, 0xe1, 0x5c, 0x6c, 0xc7, 0x3e, 0x14, 0xb5,
-	0x02, 0x0f, 0x19, 0x24, 0x46, 0xdb, 0x31, 0xf1, 0xd8, 0x6d, 0xa8, 0x0e, 0xf1, 0x2a, 0x07, 0xb5,
-	0xf0, 0xcd, 0x28, 0x68, 0x5b, 0xb0, 0x31, 0xd4, 0x1f, 0x42, 0x49, 0xaf, 0x04, 0x91, 0x41, 0x68,
-	0xac, 0xdf, 0x13, 0x8f, 0x15, 0xa6, 0x42, 0xd2, 0xe0, 0x34, 0xc1, 0x8f, 0xd7, 0x14, 0x2f, 0x43,
-	0xff, 0x04, 0x66, 0x64, 0x7d, 0x68, 0xda, 0x6f, 0xb4, 0x43, 0x64, 0xda, 0x6f, 0xac, 0xb8, 0x34,
-	0x24, 0x02, 0x1c, 0x96, 0xe5, 0xc1, 0x2a, 0x40, 0x4b, 0x48, 0x5a, 0x46, 0x24, 0x41, 0x86, 0x3d,
-	0x8f, 0x24, 0x48, 0xad, 0x06, 0x99, 0x08, 0x79, 0x4c, 0x7c, 0x79, 0x97, 0x55, 0x82, 0x8f, 0x12,
-	0x24, 0xea, 0xd1, 0x10, 0x4f, 0x62, 0x91, 0xa8, 0x98, 0xa3, 0x2e, 0xe3, 0x57, 0x0c, 0xa8, 0x32,
-	0x14, 0xa2, 0xcf, 0x00, 0xc2, 0x62, 0x36, 0xfe, 0x3a, 0x36, 0x76, 0xc4, 0xe2, 0xaf, 0x63, 0x73,
-	0x3d, 0x6c, 0xf0, 0xe0, 0x10, 0x5c, 0xfc, 0xcc, 0x85, 0xc1, 0xff, 0x2c, 0x03, 0x68, 0xbc, 0xf8,
-	0x45, 0xaf, 0x9b, 0x21, 0x8c, 0xcd, 0x36, 0xeb, 0x8d, 0xab, 0x31, 0x27, 0x46, 0xcf, 0x50, 0xaf,
-	0x16, 0x5f, 0x32, 0x7c, 0xc9, 0x34, 0xfb, 0x22, 0x03, 0x73, 0x91, 0xf2, 0x19, 0x3d, 0x4a, 0x38,
-	0xe7, 0x58, 0xc3, 0xce, 0x7a, 0x7c, 0x29, 0x5f, 0x62, 0xc6, 0xa2, 0xdd, 0x0a, 0x95, 0xad, 0xfd,
-	0x84, 0x26, 0x4d, 0xd1, 0x9a, 0x1b, 0x25, 0x00, 0x8c, 0x75, 0xfd, 0xac, 0x27, 0x97, 0x33, 0x5e,
-	0xe1, 0xb4, 0xc2, 0x04, 0x8e, 0xba, 0x85, 0x2c, 0xd5, 0x4d, 0x6e, 0x11, 0x6d, 0x1a, 0x9a, 0xdc,
-	0x22, 0x56, 0xe7, 0x27, 0xb9, 0x05, 0xab, 0x7a, 0x35, 0x4f, 0x94, 0x05, 0x7d, 0x12, 0xe4, 0x64,
-	0x4f, 0x8c, 0x75, 0x03, 0x26, 0x42, 0x86, 0x9e, 0xa8, 0xca, 0x79, 0x94, 0x20, 0xf1, 0x12, 0x4f,
-	0x8c, 0x77, 0x03, 0x92, 0x3c, 0x91, 0xa3, 0x6a, 0x9e, 0x18, 0x56, 0xdf, 0x26, 0x4f, 0x1c, 0x6b,
-	0x89, 0x9a, 0x3c, 0x71, 0xbc, 0x80, 0x4f, 0x3a, 0x5b, 0x0e, 0x1e, 0xf1, 0xc4, 0x05, 0x43, 0xb5,
-	0x8e, 0xde, 0x48, 0xb0, 0xa9, 0xb1, 0xdd, 0x6a, 0xbd, 0x79, 0x45, 0xee, 0xc9, 0x1e, 0x20, 0x4e,
-	0x43, 0x79, 0xc0, 0x2f, 0x33, 0xb0, 0x68, 0x2a, 0xf7, 0x51, 0x02, 0x58, 0x42, 0xaf, 0xd6, 0x5a,
-	0xbb, 0x2a, 0xfb, 0x15, 0xec, 0x16, 0xf8, 0xc4, 0x46, 0xe9, 0x77, 0x7f, 0x5d, 0xc9, 0xfc, 0x91,
-	0xfe, 0xfb, 0x0b, 0xfd, 0x77, 0x34, 0xcd, 0x7f, 0x4f, 0xfd, 0xf6, 0x7f, 0x02, 0x00, 0x00, 0xff,
-	0xff, 0x23, 0x65, 0x8c, 0x0e, 0xd6, 0x2d, 0x00, 0x00,
+	0x11, 0xde, 0x79, 0xe8, 0x31, 0x39, 0xa3, 0x59, 0x6d, 0x49, 0xbb, 0x1e, 0xf5, 0x6a, 0xb5, 0xda,
+	0xda, 0xa7, 0x5f, 0x1a, 0x2c, 0x1b, 0x0e, 0x40, 0x38, 0x62, 0xa4, 0x19, 0xd6, 0xb2, 0x64, 0x69,
+	0xdd, 0x9a, 0x95, 0x4d, 0x04, 0x81, 0xa2, 0x35, 0x53, 0x2b, 0x4d, 0x68, 0x5e, 0xee, 0xee, 0xd1,
+	0x4a, 0x06, 0x22, 0x08, 0x07, 0x3e, 0xc0, 0xd5, 0x07, 0x02, 0x38, 0xf2, 0x1b, 0xb8, 0xf1, 0x03,
+	0x08, 0x2e, 0x38, 0x82, 0x23, 0x17, 0x82, 0xe0, 0xc0, 0x81, 0x3b, 0xc1, 0x09, 0xea, 0xd9, 0x5d,
+	0xdd, 0x53, 0x3d, 0x92, 0x69, 0x7c, 0xd8, 0x55, 0x57, 0x56, 0x56, 0x7e, 0x59, 0x59, 0x95, 0xd9,
+	0x99, 0xd9, 0x03, 0x05, 0x77, 0xd8, 0x5a, 0x1b, 0xba, 0x03, 0x7f, 0x80, 0x4a, 0xc4, 0x6f, 0xb5,
+	0x3d, 0xe2, 0x9e, 0x11, 0x77, 0x78, 0x64, 0x2d, 0x1e, 0x0f, 0x8e, 0x07, 0x7c, 0xa2, 0xca, 0x9e,
+	0x04, 0x8f, 0xb5, 0xc4, 0x78, 0xaa, 0xbd, 0xb3, 0x56, 0x8b, 0xff, 0x37, 0x3c, 0xaa, 0x9e, 0x9e,
+	0xc9, 0xa9, 0xdb, 0x7c, 0xca, 0x19, 0xf9, 0x27, 0xfc, 0x3f, 0x3a, 0xc5, 0xfe, 0xc8, 0xc9, 0xe5,
+	0xe3, 0xc1, 0xe0, 0xb8, 0x4b, 0xaa, 0xce, 0xb0, 0x53, 0x75, 0xfa, 0xfd, 0x81, 0xef, 0xf8, 0x9d,
+	0x41, 0xdf, 0x13, 0xb3, 0xf8, 0xf3, 0x0c, 0x94, 0x6d, 0xe2, 0x0d, 0x29, 0x85, 0xbc, 0x47, 0x9c,
+	0x36, 0x71, 0xd1, 0x1d, 0x80, 0x56, 0x77, 0xe4, 0xf9, 0xc4, 0x3d, 0xec, 0xb4, 0x2b, 0x99, 0xd5,
+	0xcc, 0x93, 0xbc, 0x5d, 0x90, 0x94, 0xad, 0x36, 0xba, 0x0d, 0x85, 0x1e, 0xe9, 0x1d, 0x89, 0xd9,
+	0x2c, 0x9f, 0x9d, 0x15, 0x04, 0x3a, 0x69, 0xc1, 0xac, 0x4b, 0xce, 0x3a, 0x1e, 0x45, 0xa8, 0xe4,
+	0xe8, 0x5c, 0xce, 0x0e, 0xc6, 0x6c, 0xa1, 0xeb, 0xbc, 0xf0, 0x0f, 0xa9, 0x98, 0x5e, 0x25, 0x2f,
+	0x16, 0x32, 0x42, 0x93, 0x8e, 0xf1, 0x97, 0x39, 0x28, 0xd9, 0x4e, 0xff, 0x98, 0xd8, 0xe4, 0x93,
+	0x11, 0xf1, 0x7c, 0x34, 0x0f, 0xb9, 0x53, 0x72, 0xc1, 0xe1, 0x4b, 0x36, 0x7b, 0x14, 0xeb, 0x29,
+	0xc7, 0x21, 0xe9, 0x0b, 0xe0, 0x12, 0x5b, 0x4f, 0x09, 0x8d, 0x7e, 0x1b, 0x2d, 0xc2, 0x54, 0xb7,
+	0xd3, 0xeb, 0xf8, 0x12, 0x55, 0x0c, 0x22, 0xea, 0xe4, 0x63, 0xea, 0x6c, 0x02, 0x78, 0x03, 0xd7,
+	0x3f, 0x1c, 0xb8, 0x74, 0xd3, 0x95, 0x29, 0x3a, 0x5b, 0x5e, 0x7f, 0xb0, 0xa6, 0x1f, 0xc4, 0x9a,
+	0xae, 0xd0, 0xda, 0x3e, 0x65, 0xde, 0x63, 0xbc, 0x76, 0xc1, 0x53, 0x8f, 0xe8, 0x7b, 0x50, 0xe4,
+	0x42, 0x7c, 0xc7, 0x3d, 0x26, 0x7e, 0x65, 0x9a, 0x4b, 0x79, 0x78, 0x89, 0x94, 0x26, 0x67, 0xb6,
+	0x39, 0xbc, 0x78, 0x46, 0x18, 0x4a, 0x94, 0xbf, 0xe3, 0x74, 0x3b, 0x9f, 0x3a, 0x47, 0x5d, 0x52,
+	0x99, 0xa1, 0x82, 0x66, 0xed, 0x08, 0x8d, 0xed, 0x9f, 0x9a, 0xc1, 0x3b, 0x1c, 0xf4, 0xbb, 0x17,
+	0x95, 0x59, 0xce, 0x30, 0xcb, 0x08, 0x7b, 0x74, 0xcc, 0x0f, 0x6d, 0x30, 0xea, 0xfb, 0x62, 0xb6,
+	0xc0, 0x67, 0x0b, 0x9c, 0xc2, 0xa6, 0xf1, 0x1a, 0x14, 0x02, 0xfd, 0xd1, 0x2c, 0xe4, 0x77, 0xf7,
+	0x76, 0x1b, 0xf3, 0xd7, 0x10, 0xc0, 0x74, 0x6d, 0x7f, 0xb3, 0xb1, 0x5b, 0x9f, 0xcf, 0xa0, 0x22,
+	0xcc, 0xd4, 0x1b, 0x62, 0x90, 0xc5, 0x1b, 0x00, 0xa1, 0xa6, 0x68, 0x06, 0x72, 0xdb, 0x8d, 0xef,
+	0x53, 0x7e, 0xca, 0x73, 0xd0, 0xb0, 0xf7, 0xb7, 0xf6, 0x76, 0xe9, 0x02, 0xba, 0x78, 0xd3, 0x6e,
+	0xd4, 0x9a, 0x8d, 0xf9, 0x2c, 0xe3, 0xf8, 0x60, 0xaf, 0x3e, 0x9f, 0x43, 0x05, 0x98, 0x3a, 0xa8,
+	0xed, 0x3c, 0x6f, 0xcc, 0xe7, 0xf1, 0x17, 0x19, 0x98, 0x93, 0x7b, 0x17, 0xf7, 0x0b, 0xbd, 0x03,
+	0xd3, 0x27, 0xfc, 0x8e, 0xf1, 0x63, 0x2d, 0xae, 0x2f, 0xc7, 0x0c, 0x15, 0xb9, 0x87, 0xb6, 0xe4,
+	0xa5, 0xb6, 0xc9, 0x9d, 0x9e, 0x79, 0xf4, 0xc4, 0x73, 0x74, 0xc9, 0xfc, 0x9a, 0xb8, 0xfc, 0x6b,
+	0xdb, 0xe4, 0xe2, 0xc0, 0xe9, 0x8e, 0x88, 0xcd, 0x26, 0x11, 0x82, 0x7c, 0x6f, 0xe0, 0x12, 0x7e,
+	0xfa, 0xb3, 0x36, 0x7f, 0x66, 0x57, 0x82, 0x1b, 0x40, 0x9e, 0xbc, 0x18, 0xe0, 0xf7, 0x01, 0x9e,
+	0x8d, 0xfc, 0xe4, 0x5b, 0x46, 0x57, 0x9d, 0x31, 0xb9, 0xf2, 0x86, 0x89, 0x01, 0xbf, 0x5e, 0xc4,
+	0xf1, 0x48, 0x70, 0xbd, 0xd8, 0x00, 0x6f, 0x42, 0x91, 0xcb, 0x4a, 0xb3, 0x3d, 0x2a, 0x04, 0xd5,
+	0x49, 0x97, 0xf8, 0x24, 0xc5, 0xf5, 0xc7, 0x04, 0x16, 0x22, 0x42, 0x52, 0x19, 0xbc, 0x02, 0x33,
+	0x6d, 0x2e, 0x4c, 0xe0, 0xe4, 0x6c, 0x35, 0xc4, 0xff, 0xcc, 0x40, 0x41, 0x6a, 0xb8, 0x37, 0x44,
+	0x35, 0x98, 0x73, 0xc5, 0xe0, 0x90, 0x2b, 0x22, 0x41, 0xac, 0xe4, 0xeb, 0xff, 0xde, 0x35, 0xbb,
+	0x24, 0x97, 0x70, 0x32, 0xfa, 0x0e, 0x14, 0x95, 0x88, 0xe1, 0xc8, 0xe7, 0x70, 0xc5, 0xf5, 0x4a,
+	0x54, 0x40, 0x78, 0x5c, 0x74, 0x39, 0x48, 0x76, 0x4a, 0x44, 0x4d, 0x58, 0x54, 0x8b, 0x85, 0x82,
+	0x52, 0x8d, 0x1c, 0x97, 0xb2, 0x1a, 0x95, 0x32, 0x6e, 0x63, 0x2a, 0x0d, 0xc9, 0xf5, 0xda, 0xe4,
+	0x46, 0x01, 0x66, 0x24, 0x15, 0xff, 0x2b, 0x03, 0xa0, 0x6c, 0x44, 0xf7, 0x5b, 0x87, 0xb2, 0x2b,
+	0x47, 0x91, 0x0d, 0xdf, 0x36, 0x6e, 0x58, 0x9a, 0xf6, 0x9a, 0x3d, 0xa7, 0x16, 0x89, 0x2d, 0xbf,
+	0x0b, 0xa5, 0x40, 0x4a, 0xb8, 0xe7, 0x25, 0xc3, 0x9e, 0x03, 0x09, 0x45, 0xb5, 0x80, 0xed, 0xfa,
+	0x23, 0xb8, 0x19, 0xac, 0x37, 0x6c, 0xfb, 0xde, 0x84, 0x6d, 0x07, 0x02, 0x17, 0x94, 0x04, 0x7d,
+	0xe3, 0xc0, 0x82, 0xa5, 0x20, 0xe3, 0x5f, 0xe7, 0x60, 0x66, 0x73, 0xd0, 0x1b, 0x3a, 0x2e, 0x3b,
+	0xa3, 0x69, 0x4a, 0x1f, 0x75, 0x7d, 0xbe, 0xdd, 0xf2, 0xfa, 0xfd, 0x28, 0x82, 0x64, 0x53, 0x7f,
+	0x6d, 0xce, 0x6a, 0xcb, 0x25, 0x6c, 0xb1, 0x8c, 0x8d, 0xd9, 0x2b, 0x2c, 0x96, 0x91, 0x51, 0x2e,
+	0x51, 0x4e, 0x90, 0x0b, 0x9d, 0xc0, 0x82, 0x19, 0xba, 0x30, 0x8c, 0xe7, 0x74, 0x2f, 0x8a, 0x80,
+	0x5e, 0x85, 0xeb, 0x2d, 0x97, 0x38, 0xcc, 0x1e, 0x2a, 0xe6, 0x4f, 0x49, 0x9e, 0xb2, 0x98, 0xb0,
+	0x55, 0xec, 0xbf, 0x0f, 0xa5, 0xde, 0xa0, 0x1d, 0xf2, 0x4d, 0x4b, 0xbe, 0x22, 0xa5, 0x06, 0x4c,
+	0xb7, 0x54, 0x24, 0x60, 0xc1, 0xb8, 0x44, 0x67, 0xc5, 0x10, 0xbf, 0x05, 0x73, 0x91, 0xbd, 0xb2,
+	0x98, 0xd7, 0xf8, 0xf0, 0x79, 0x6d, 0x47, 0x04, 0xc8, 0xa7, 0x3c, 0x26, 0xda, 0x34, 0x40, 0xd2,
+	0x38, 0xbb, 0xd3, 0xd8, 0xdf, 0xa7, 0xe1, 0xf4, 0xbb, 0xc1, 0x12, 0x19, 0x51, 0xb5, 0x40, 0x7a,
+	0x4d, 0x0b, 0xa4, 0x19, 0x15, 0x48, 0xb3, 0x61, 0x20, 0xcd, 0x6d, 0x94, 0xa1, 0x24, 0x0c, 0x72,
+	0x38, 0xea, 0x53, 0xc5, 0xf0, 0x6f, 0xe9, 0xb5, 0x6c, 0x9e, 0xf7, 0x55, 0xa8, 0xa8, 0xc2, 0x4c,
+	0x4b, 0x08, 0xa7, 0x07, 0xc4, 0x62, 0xe4, 0x4d, 0xa3, 0x8d, 0x6d, 0xc5, 0x85, 0xde, 0x82, 0x19,
+	0x6f, 0xd4, 0x6a, 0x11, 0x4f, 0x05, 0xd5, 0x57, 0xe2, 0x61, 0x41, 0x7a, 0xb8, 0xad, 0xf8, 0xd8,
+	0x92, 0x17, 0x4e, 0xa7, 0x3b, 0xe2, 0x21, 0x76, 0xf2, 0x12, 0xc9, 0x87, 0x7f, 0x95, 0x81, 0x22,
+	0xd7, 0x32, 0x55, 0x2c, 0x5a, 0x86, 0x02, 0xd7, 0x81, 0xb4, 0x65, 0x34, 0xa2, 0xaf, 0xb5, 0x80,
+	0x80, 0xbe, 0x45, 0x63, 0xa2, 0x5c, 0xe7, 0x49, 0xc5, 0x2a, 0x66, 0xb1, 0x54, 0xb3, 0x90, 0x15,
+	0x6f, 0xc3, 0x0d, 0x6e, 0x95, 0x16, 0x4b, 0x85, 0x94, 0x1d, 0xf5, 0x64, 0x21, 0x13, 0x4b, 0x16,
+	0xe8, 0xdc, 0xf0, 0xe4, 0xc2, 0xeb, 0xb4, 0x9c, 0xae, 0xd4, 0x22, 0x18, 0xd3, 0x37, 0x0a, 0xd2,
+	0x85, 0xa5, 0x7a, 0x19, 0xcc, 0x41, 0xf1, 0x3d, 0xc7, 0x3b, 0x91, 0x2a, 0xe1, 0x8f, 0xa1, 0x24,
+	0x86, 0xa9, 0x6c, 0x48, 0x5f, 0x8e, 0x27, 0x54, 0x0a, 0x57, 0x7c, 0xce, 0xe6, 0xcf, 0xf8, 0x06,
+	0x5c, 0xdf, 0xef, 0x3b, 0x43, 0xef, 0x64, 0xa0, 0x82, 0x2b, 0x4b, 0x05, 0xe7, 0x43, 0x5a, 0x2a,
+	0xc4, 0xc7, 0x70, 0xdd, 0x25, 0x3d, 0xa7, 0xd3, 0xef, 0xf4, 0x8f, 0x0f, 0x8f, 0x2e, 0x7c, 0xe2,
+	0xc9, 0x4c, 0xb1, 0x1c, 0x90, 0x37, 0x18, 0x95, 0xa9, 0x76, 0xd4, 0x1d, 0x1c, 0x49, 0x17, 0xe7,
+	0xcf, 0xf8, 0x77, 0x19, 0x28, 0x7d, 0xe4, 0xf8, 0x2d, 0x65, 0x05, 0xb4, 0x05, 0xe5, 0xc0, 0xb1,
+	0x39, 0x45, 0xea, 0x12, 0x8b, 0xf0, 0x7c, 0xcd, 0xa6, 0x74, 0x74, 0x15, 0xe1, 0xe7, 0x5a, 0x3a,
+	0x81, 0x8b, 0x72, 0xfa, 0x2d, 0xd2, 0x0d, 0x44, 0x65, 0x93, 0x45, 0x71, 0x46, 0x5d, 0x94, 0x4e,
+	0xd8, 0xb8, 0x1e, 0xbe, 0xfd, 0x84, 0x5b, 0xd2, 0x7c, 0x07, 0x8d, 0xeb, 0xf0, 0x55, 0x13, 0xd9,
+	0x87, 0x50, 0xf6, 0xa8, 0xb7, 0xfb, 0x87, 0xb1, 0x3c, 0x7a, 0x8e, 0x53, 0x83, 0xe0, 0x44, 0x2d,
+	0x4c, 0x13, 0xf8, 0x63, 0x7a, 0xa5, 0xbd, 0x43, 0x9a, 0xd3, 0x77, 0x5e, 0x5c, 0xf0, 0x80, 0x38,
+	0x6b, 0x97, 0x15, 0x79, 0x97, 0x53, 0x71, 0x55, 0x29, 0xa5, 0x2b, 0x8f, 0x96, 0x60, 0xf6, 0x25,
+	0xa3, 0xaa, 0x0c, 0x9f, 0xbe, 0xe3, 0xf9, 0x78, 0xab, 0x8d, 0xff, 0x41, 0xd3, 0x36, 0x69, 0xfe,
+	0x54, 0x77, 0x40, 0x87, 0xc8, 0x46, 0x20, 0x58, 0x82, 0x21, 0x8e, 0xa5, 0x2d, 0x13, 0x36, 0x35,
+	0x64, 0x7e, 0x26, 0xac, 0x4c, 0xa7, 0xc4, 0x7e, 0x82, 0x31, 0x8d, 0xef, 0xf3, 0x2d, 0xe1, 0x67,
+	0xb1, 0x00, 0x6f, 0x5f, 0x97, 0xf4, 0xc0, 0x3a, 0x0f, 0x61, 0x9a, 0x9c, 0x91, 0xbe, 0xef, 0x55,
+	0x8a, 0x3c, 0x28, 0xcc, 0xa9, 0xac, 0xb1, 0xc1, 0xa8, 0xb6, 0x9c, 0xc4, 0xdf, 0x84, 0x1b, 0x3b,
+	0x2c, 0x91, 0x7b, 0x4a, 0xad, 0xaf, 0xa7, 0x84, 0xcd, 0xe6, 0x8e, 0xb4, 0x4a, 0xce, 0x6f, 0xee,
+	0xa0, 0x32, 0x64, 0xb7, 0xea, 0x72, 0x0f, 0xd9, 0x4e, 0x1d, 0x7f, 0x46, 0x0f, 0x5a, 0x5f, 0x97,
+	0xca, 0x4c, 0x31, 0xe1, 0x0a, 0x3e, 0x17, 0xc2, 0xd3, 0xdc, 0x93, 0xb8, 0xee, 0xc0, 0xe5, 0x06,
+	0x29, 0xd8, 0x62, 0x80, 0x1f, 0x48, 0x1d, 0xe8, 0x9e, 0x07, 0xa7, 0xc1, 0x65, 0x13, 0xd2, 0x32,
+	0x81, 0xaa, 0xdb, 0xb0, 0x10, 0xe1, 0x4a, 0x15, 0x9c, 0x1e, 0xc3, 0x4d, 0x2e, 0x6c, 0x9b, 0x90,
+	0x61, 0xad, 0xdb, 0x39, 0x4b, 0x44, 0x1d, 0xc2, 0xad, 0x38, 0xe3, 0xd7, 0x6b, 0x23, 0x7c, 0x02,
+	0xd3, 0x1f, 0xf0, 0x1a, 0x54, 0xd3, 0x25, 0xcf, 0x79, 0x69, 0x84, 0xe9, 0x3b, 0x3d, 0x91, 0xce,
+	0x17, 0x6c, 0xfe, 0xcc, 0xa3, 0x39, 0x21, 0xee, 0x73, 0x7b, 0x47, 0xbc, 0x35, 0x0a, 0x76, 0x30,
+	0x46, 0x2b, 0xac, 0xfa, 0xed, 0xd0, 0xeb, 0xc1, 0x67, 0xf3, 0x7c, 0x56, 0xa3, 0xd0, 0x4a, 0x6a,
+	0x5e, 0x20, 0xd5, 0xda, 0x6d, 0xed, 0xcd, 0x11, 0xc8, 0xcb, 0x44, 0xe5, 0xe1, 0x97, 0x70, 0x43,
+	0xe3, 0x4f, 0x65, 0x86, 0x37, 0x60, 0x5a, 0x14, 0xda, 0x32, 0x68, 0x2d, 0x46, 0x57, 0x09, 0x18,
+	0x5b, 0xf2, 0xe0, 0x87, 0xb0, 0x20, 0x29, 0xa4, 0x37, 0x30, 0x9d, 0x15, 0xb7, 0x0f, 0xde, 0x81,
+	0xc5, 0x28, 0x5b, 0xaa, 0x2b, 0x52, 0x53, 0xa0, 0xcf, 0x87, 0x6d, 0x2d, 0x06, 0xc6, 0x0f, 0x45,
+	0x37, 0x58, 0x36, 0x66, 0xb0, 0x40, 0x21, 0x25, 0x22, 0x95, 0x42, 0x0b, 0xca, 0xfc, 0x3b, 0x1d,
+	0x2f, 0x78, 0xd3, 0x7d, 0x0a, 0x48, 0x27, 0xa6, 0x3a, 0x94, 0x35, 0x98, 0x11, 0x06, 0x57, 0xc9,
+	0x94, 0xf9, 0x54, 0x14, 0x13, 0x53, 0xa8, 0x4e, 0x5e, 0xb8, 0xce, 0x71, 0x8f, 0x04, 0x31, 0x87,
+	0xa5, 0x10, 0x3a, 0x31, 0xd5, 0x8e, 0xff, 0x44, 0x5f, 0x9f, 0xb5, 0xae, 0xe3, 0xf6, 0x94, 0xf1,
+	0xdf, 0x85, 0x69, 0x91, 0x9b, 0xc8, 0xfc, 0xfd, 0x51, 0x54, 0x8c, 0xce, 0x2b, 0x06, 0x35, 0x91,
+	0xc9, 0xc8, 0x55, 0xec, 0xb0, 0x64, 0x7f, 0xa7, 0x1e, 0xeb, 0xf7, 0xd4, 0xd1, 0x9b, 0x30, 0xe5,
+	0xb0, 0x25, 0xdc, 0x17, 0xcb, 0xf1, 0xac, 0x90, 0x4b, 0x6b, 0x5e, 0x0c, 0x89, 0x2d, 0xb8, 0xf0,
+	0x3b, 0x50, 0xd4, 0x10, 0x58, 0xb2, 0xfb, 0xb4, 0xd1, 0xa4, 0x19, 0x70, 0x09, 0x66, 0x6b, 0x9b,
+	0xcd, 0xad, 0x03, 0x91, 0x03, 0x97, 0x01, 0xea, 0x8d, 0x60, 0x9c, 0xa5, 0x59, 0x90, 0x58, 0x25,
+	0x3d, 0x5c, 0xd7, 0x27, 0x93, 0xa4, 0x4f, 0xf6, 0x4a, 0xfa, 0x9c, 0xc3, 0x9c, 0xdc, 0x7e, 0xaa,
+	0x3b, 0xf0, 0x16, 0xb5, 0x30, 0x13, 0xa3, 0xae, 0xc0, 0x92, 0x01, 0x56, 0x79, 0xa7, 0x60, 0xc4,
+	0x34, 0x7b, 0xd8, 0xf7, 0x1d, 0x7f, 0xe4, 0xa9, 0x2b, 0xf0, 0xc7, 0x0c, 0x94, 0x15, 0x25, 0x6d,
+	0xf5, 0xae, 0x4a, 0x24, 0x11, 0xf3, 0x82, 0x02, 0xe9, 0x16, 0x4c, 0xb7, 0x8f, 0xf6, 0x3b, 0x9f,
+	0xaa, 0x2e, 0x86, 0x1c, 0x31, 0x7a, 0x57, 0xe0, 0x88, 0xae, 0x9c, 0x1c, 0xb1, 0xdc, 0x9b, 0xf5,
+	0xe7, 0xb6, 0xfa, 0x6d, 0x72, 0xce, 0xdf, 0xb4, 0x79, 0x3b, 0x24, 0xf0, 0x74, 0x59, 0x76, 0xef,
+	0x78, 0xfd, 0xa4, 0x77, 0xf3, 0xe8, 0x25, 0xaf, 0x8d, 0xfc, 0x93, 0x46, 0x9f, 0x35, 0xae, 0xd4,
+	0x0e, 0x17, 0x01, 0x31, 0x62, 0xbd, 0xe3, 0xe9, 0xd4, 0x06, 0x2c, 0x30, 0x2a, 0xbd, 0xf7, 0x34,
+	0x99, 0x0e, 0x23, 0x86, 0x0a, 0xdb, 0x99, 0x58, 0xd8, 0x76, 0x3c, 0xef, 0xe5, 0xc0, 0x6d, 0xcb,
+	0xad, 0x05, 0x63, 0x5c, 0x17, 0xc2, 0x9f, 0x7b, 0x91, 0xc0, 0xfc, 0x55, 0xa5, 0x3c, 0x09, 0xa5,
+	0x3c, 0x25, 0xfe, 0x04, 0x29, 0xf8, 0x75, 0xb8, 0xa9, 0x38, 0x65, 0x0d, 0x3d, 0x81, 0x79, 0x0f,
+	0xee, 0x28, 0xe6, 0xcd, 0x13, 0x96, 0xe8, 0x3d, 0x93, 0x80, 0xff, 0xab, 0x9e, 0x1b, 0x50, 0x09,
+	0xf4, 0xe4, 0x39, 0xc8, 0xa0, 0xab, 0x2b, 0x30, 0xf2, 0xe4, 0x9d, 0xa1, 0xb2, 0xd8, 0x33, 0xa3,
+	0xb9, 0x94, 0x45, 0xbd, 0x04, 0xd9, 0x33, 0xde, 0x84, 0x25, 0x25, 0x43, 0x66, 0x07, 0x51, 0x21,
+	0x63, 0x0a, 0x99, 0x84, 0x48, 0x83, 0xb1, 0xa5, 0x93, 0xcd, 0xae, 0x73, 0x46, 0x4d, 0xcb, 0x65,
+	0x66, 0x34, 0x99, 0x37, 0xc5, 0x8d, 0x60, 0x8a, 0xe9, 0x41, 0x5b, 0x92, 0x99, 0x00, 0x9d, 0x2c,
+	0x0f, 0x82, 0x91, 0xc7, 0x0e, 0x62, 0x4c, 0xf4, 0x0f, 0x60, 0x25, 0x50, 0x82, 0xd9, 0xed, 0x19,
+	0xbd, 0xac, 0x1d, 0xcf, 0xd3, 0x8a, 0x40, 0xd3, 0xc6, 0x1f, 0x41, 0x7e, 0x48, 0x64, 0x4c, 0x29,
+	0xae, 0xa3, 0x35, 0xd1, 0x63, 0x5f, 0xd3, 0x16, 0xf3, 0x79, 0xdc, 0x86, 0xbb, 0x4a, 0xba, 0xb0,
+	0xa8, 0x51, 0x7c, 0x5c, 0x29, 0x55, 0x20, 0x08, 0xb3, 0x8e, 0x17, 0x08, 0x39, 0x71, 0xf6, 0x41,
+	0xab, 0xef, 0x7d, 0x61, 0x48, 0xe5, 0x5b, 0xa9, 0xde, 0x15, 0xdb, 0xc2, 0xa6, 0x81, 0x4b, 0xa6,
+	0x12, 0x76, 0x04, 0x8b, 0x51, 0x4f, 0x4e, 0x15, 0xc6, 0x68, 0xd6, 0xeb, 0x53, 0x13, 0xaa, 0x20,
+	0x26, 0x06, 0x4a, 0xe1, 0xc0, 0xcd, 0x53, 0x29, 0xec, 0x84, 0xc2, 0xf8, 0x95, 0x4c, 0xab, 0x2f,
+	0x3b, 0x4d, 0x95, 0xcf, 0x88, 0x01, 0xde, 0x85, 0x5b, 0xf1, 0x30, 0x91, 0x4a, 0xe5, 0x03, 0x71,
+	0x81, 0x4d, 0x91, 0x24, 0x95, 0xdc, 0x0f, 0xc3, 0x60, 0xa0, 0x05, 0x94, 0x54, 0x22, 0x6d, 0xb0,
+	0x4c, 0xf1, 0xe5, 0xff, 0x71, 0x5f, 0x83, 0x70, 0x93, 0x4a, 0x98, 0x17, 0x0a, 0x4b, 0x7f, 0xfc,
+	0x61, 0x8c, 0xc8, 0x4d, 0x8c, 0x11, 0xd2, 0x49, 0xc2, 0x28, 0xf6, 0x35, 0x5c, 0x3a, 0x89, 0x11,
+	0x06, 0xd0, 0xb4, 0x18, 0xec, 0x1d, 0x12, 0x60, 0xf0, 0x81, 0xba, 0xd8, 0x7a, 0xd8, 0x4d, 0x75,
+	0x18, 0x1f, 0x85, 0xb1, 0x73, 0x2c, 0x32, 0xa7, 0x12, 0xfc, 0x31, 0xac, 0x26, 0x07, 0xe5, 0x34,
+	0x92, 0x5f, 0xc3, 0x50, 0x08, 0x12, 0x4a, 0xed, 0x9b, 0x5a, 0x11, 0x66, 0x76, 0xf7, 0xf6, 0x9f,
+	0xd5, 0x36, 0x69, 0x2a, 0xbb, 0xfe, 0x97, 0x1c, 0x64, 0xb7, 0x0f, 0xd0, 0x0f, 0x61, 0x4a, 0x34,
+	0xff, 0x27, 0x7c, 0x1b, 0xb1, 0x26, 0x7d, 0x46, 0xc0, 0xcb, 0x9f, 0xfd, 0xf9, 0xef, 0x5f, 0x64,
+	0x6f, 0xe1, 0x1b, 0xd5, 0xb3, 0xb7, 0x9d, 0xee, 0xf0, 0xc4, 0xa9, 0x9e, 0x9e, 0x55, 0xf9, 0x3b,
+	0xe1, 0xdb, 0x99, 0xd7, 0xd0, 0x01, 0xe4, 0xd8, 0xa7, 0x81, 0xc4, 0x0f, 0x27, 0x56, 0xf2, 0xe7,
+	0x05, 0x6c, 0x71, 0xc9, 0x8b, 0xf8, 0xba, 0x2e, 0x79, 0x38, 0xf2, 0x99, 0xdc, 0x26, 0x14, 0xb5,
+	0x2f, 0x04, 0xe8, 0xd2, 0x4f, 0x2a, 0xd6, 0xe5, 0x5f, 0x1f, 0xf0, 0x35, 0xa6, 0x6d, 0xf3, 0xbc,
+	0x1f, 0xd7, 0x36, 0xec, 0x68, 0xc7, 0xb5, 0xd5, 0xba, 0xc8, 0x66, 0x6d, 0xfd, 0xf3, 0x3e, 0xd3,
+	0x76, 0x20, 0xbf, 0x59, 0xb4, 0x7c, 0x74, 0xd7, 0xd0, 0x02, 0xd7, 0x9b, 0xbd, 0xd6, 0x6a, 0x32,
+	0x83, 0x44, 0xba, 0xc7, 0x91, 0x6e, 0xe3, 0x5b, 0x3a, 0x52, 0x2b, 0xe0, 0xa3, 0x80, 0xeb, 0x27,
+	0x30, 0xc5, 0x3b, 0x65, 0xe8, 0x50, 0x3d, 0x58, 0x86, 0x3e, 0x62, 0xc2, 0xf9, 0x46, 0x7a, 0x6c,
+	0x78, 0x89, 0xa3, 0x2d, 0xe0, 0x72, 0x80, 0xc6, 0x9b, 0x65, 0x14, 0xe5, 0x49, 0xe6, 0x1b, 0x99,
+	0xf5, 0x7f, 0x67, 0x61, 0x8a, 0xb7, 0x54, 0xd0, 0x10, 0x20, 0xec, 0x3d, 0xc5, 0xf7, 0x39, 0xd6,
+	0xcd, 0x8a, 0xef, 0x73, 0xbc, 0x6d, 0x85, 0xef, 0x72, 0xe4, 0x25, 0xbc, 0x18, 0x20, 0xf3, 0x8f,
+	0x9b, 0xd5, 0x63, 0xc6, 0xc5, 0xcc, 0xfa, 0x12, 0x8a, 0x5a, 0x0f, 0x09, 0x99, 0x24, 0x46, 0x9a,
+	0x50, 0xf1, 0x4b, 0x60, 0x68, 0x40, 0xe1, 0xfb, 0x1c, 0xf4, 0x0e, 0xae, 0xe8, 0xc6, 0x15, 0xb8,
+	0x2e, 0xe7, 0x64, 0xc0, 0x3f, 0xa3, 0x25, 0x51, 0xb4, 0x8f, 0x84, 0xee, 0x1b, 0x44, 0xc7, 0xdb,
+	0x51, 0xd6, 0x83, 0xc9, 0x4c, 0x89, 0x2a, 0x08, 0xfc, 0x53, 0xca, 0xe9, 0x30, 0x4e, 0x65, 0xfb,
+	0xff, 0xb0, 0x6f, 0x61, 0xe2, 0xe7, 0x0f, 0xc8, 0x87, 0x42, 0xd0, 0xcd, 0x41, 0x2b, 0xa6, 0x4a,
+	0x3f, 0x4c, 0x83, 0xad, 0xbb, 0x89, 0xf3, 0x52, 0x85, 0x47, 0x5c, 0x85, 0x55, 0x7c, 0x3b, 0x50,
+	0x41, 0xfe, 0xcc, 0xa2, 0x2a, 0x0a, 0xda, 0xaa, 0xd3, 0x6e, 0x33, 0x43, 0xfc, 0x94, 0x96, 0xf4,
+	0x7a, 0x93, 0x06, 0xdd, 0x33, 0xf6, 0x18, 0xf4, 0x3e, 0x8f, 0x85, 0x27, 0xb1, 0x48, 0xfc, 0x57,
+	0x39, 0xfe, 0x7d, 0xbc, 0x92, 0x84, 0xef, 0x72, 0xfe, 0xa8, 0x0a, 0xa2, 0x2d, 0x63, 0x56, 0x21,
+	0xd2, 0xf5, 0x31, 0xab, 0x10, 0xed, 0xea, 0x5c, 0xae, 0xc2, 0x88, 0xf3, 0x33, 0x15, 0xce, 0x01,
+	0xc2, 0xae, 0x0d, 0x32, 0x1a, 0x57, 0x2b, 0x0c, 0xe2, 0x37, 0x7f, 0xbc, 0xe1, 0x83, 0x1f, 0x73,
+	0xec, 0x7b, 0x78, 0x39, 0x09, 0xbb, 0x4b, 0xb9, 0x99, 0x9f, 0xff, 0x3e, 0x0f, 0xc5, 0x0f, 0x9c,
+	0x4e, 0xdf, 0x27, 0x7d, 0xd6, 0x8c, 0x46, 0xc7, 0x30, 0xc5, 0x23, 0x7f, 0xdc, 0xdd, 0xf5, 0x56,
+	0x4a, 0xdc, 0xdd, 0x23, 0x7d, 0x06, 0xfc, 0x90, 0x43, 0xdf, 0xc5, 0x56, 0x00, 0xdd, 0x0b, 0xe5,
+	0x57, 0x79, 0x8f, 0x80, 0x6d, 0xf9, 0x14, 0xa6, 0x45, 0x4f, 0x00, 0xc5, 0xa4, 0x45, 0x7a, 0x07,
+	0xd6, 0xb2, 0x79, 0x32, 0xf1, 0x96, 0xe9, 0x58, 0x1e, 0x67, 0x66, 0x60, 0x3f, 0x02, 0x08, 0x9b,
+	0x50, 0x71, 0xfb, 0x8e, 0xf5, 0xac, 0xac, 0xd5, 0x64, 0x06, 0x09, 0xfc, 0x1a, 0x07, 0x7e, 0x80,
+	0xef, 0x1a, 0x81, 0xdb, 0xc1, 0x02, 0x06, 0xde, 0x82, 0x3c, 0xfb, 0xd2, 0x85, 0x62, 0xa1, 0x5f,
+	0xfb, 0x18, 0x66, 0x59, 0xa6, 0x29, 0x09, 0xf5, 0x80, 0x43, 0xad, 0xe0, 0x25, 0x23, 0x14, 0xfb,
+	0xe2, 0xc5, 0x40, 0x46, 0x30, 0xab, 0x3e, 0x70, 0xa1, 0x3b, 0x31, 0x9b, 0x45, 0x3f, 0x86, 0x59,
+	0x2b, 0x49, 0xd3, 0x12, 0xf0, 0x09, 0x07, 0xc4, 0xf8, 0x8e, 0xd9, 0xa8, 0x92, 0x9d, 0x82, 0xd2,
+	0x00, 0xf2, 0x8b, 0x79, 0xc8, 0xb3, 0x1c, 0x84, 0xc5, 0xee, 0xb0, 0x74, 0x8b, 0x5b, 0x78, 0xac,
+	0x61, 0x12, 0xb7, 0xf0, 0x78, 0xd5, 0x67, 0x88, 0xdd, 0xfc, 0x47, 0x60, 0x84, 0x73, 0xb1, 0x1d,
+	0xfb, 0x50, 0xd4, 0x0a, 0x3c, 0x64, 0x90, 0x18, 0x6d, 0xc7, 0xc4, 0x63, 0xb7, 0xa1, 0x3a, 0xc4,
+	0xab, 0x1c, 0xd4, 0xc2, 0x37, 0xa3, 0xa0, 0x6d, 0xc1, 0xc6, 0x50, 0x7f, 0x0c, 0x25, 0xbd, 0x12,
+	0x44, 0x06, 0xa1, 0xb1, 0x7e, 0x4f, 0x3c, 0x56, 0x98, 0x0a, 0x49, 0x83, 0xd3, 0x04, 0x3f, 0x79,
+	0x53, 0xbc, 0x0c, 0xfd, 0x13, 0x98, 0x91, 0xf5, 0xa1, 0x69, 0xbf, 0xd1, 0x0e, 0x91, 0x69, 0xbf,
+	0xb1, 0xe2, 0xd2, 0x90, 0x08, 0x70, 0x58, 0x96, 0x07, 0xab, 0x00, 0x2d, 0x21, 0x69, 0x19, 0x91,
+	0x04, 0x19, 0xf6, 0x3c, 0x92, 0x20, 0xb5, 0x1a, 0x64, 0x22, 0xe4, 0x31, 0xf1, 0xe5, 0x5d, 0x56,
+	0x09, 0x3e, 0x4a, 0x90, 0xa8, 0x47, 0x43, 0x3c, 0x89, 0x45, 0xa2, 0x62, 0x8e, 0xba, 0x8c, 0x5f,
+	0x31, 0xa0, 0xca, 0x50, 0x88, 0x7e, 0x02, 0x10, 0x16, 0xb3, 0xf1, 0xd7, 0xb1, 0xb1, 0x23, 0x16,
+	0x7f, 0x1d, 0x9b, 0xeb, 0x61, 0x83, 0x07, 0x87, 0xe0, 0xe2, 0x67, 0x2e, 0x0c, 0xfe, 0x97, 0x19,
+	0x40, 0xe3, 0xc5, 0x2f, 0x7a, 0xdd, 0x0c, 0x61, 0x6c, 0xb6, 0x59, 0x6f, 0x5c, 0x8d, 0x39, 0x31,
+	0x7a, 0x86, 0x7a, 0xb5, 0xf8, 0x92, 0xe1, 0x4b, 0xa6, 0xd9, 0xe7, 0x19, 0x98, 0x8b, 0x94, 0xcf,
+	0xe8, 0x51, 0xc2, 0x39, 0xc7, 0x1a, 0x76, 0xd6, 0xe3, 0x4b, 0xf9, 0x12, 0x33, 0x16, 0xed, 0x56,
+	0xa8, 0x6c, 0xed, 0xe7, 0x34, 0x69, 0x8a, 0xd6, 0xdc, 0x28, 0x01, 0x60, 0xac, 0xeb, 0x67, 0x3d,
+	0xb9, 0x9c, 0xf1, 0x0a, 0xa7, 0x15, 0x26, 0x70, 0xd4, 0x2d, 0x64, 0xa9, 0x6e, 0x72, 0x8b, 0x68,
+	0xd3, 0xd0, 0xe4, 0x16, 0xb1, 0x3a, 0x3f, 0xc9, 0x2d, 0x58, 0xd5, 0xab, 0x79, 0xa2, 0x2c, 0xe8,
+	0x93, 0x20, 0x27, 0x7b, 0x62, 0xac, 0x1b, 0x30, 0x11, 0x32, 0xf4, 0x44, 0x55, 0xce, 0xa3, 0x04,
+	0x89, 0x97, 0x78, 0x62, 0xbc, 0x1b, 0x90, 0xe4, 0x89, 0x1c, 0x55, 0xf3, 0xc4, 0xb0, 0xfa, 0x36,
+	0x79, 0xe2, 0x58, 0x4b, 0xd4, 0xe4, 0x89, 0xe3, 0x05, 0x7c, 0xd2, 0xd9, 0x72, 0xf0, 0x88, 0x27,
+	0x2e, 0x18, 0xaa, 0x75, 0xf4, 0x46, 0x82, 0x4d, 0x8d, 0xed, 0x56, 0xeb, 0xcd, 0x2b, 0x72, 0x4f,
+	0xf6, 0x00, 0x71, 0x1a, 0xca, 0x03, 0x7e, 0x93, 0x81, 0x45, 0x53, 0xb9, 0x8f, 0x12, 0xc0, 0x12,
+	0x7a, 0xb5, 0xd6, 0xda, 0x55, 0xd9, 0xaf, 0x60, 0xb7, 0xc0, 0x27, 0x36, 0x4a, 0x7f, 0xf8, 0xdb,
+	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,
 }
 }

+ 6 - 0
etcdserver/etcdserverpb/rpc.proto

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

+ 14 - 2
mvcc/kv.go

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

+ 57 - 57
mvcc/kv_test.go

@@ -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) {
-		return kv.Range(key, end, limit, rangeRev)
+	normalRangeFunc = func(kv KV, key, end []byte, ro RangeOptions) (*RangeResult, error) {
+		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 {
-			t.Errorf("#%d: rev = %d, want %d", i, rev, wrev)
+		if r.Rev != wrev {
+			t.Errorf("#%d: rev = %d, want %d", i, r.Rev, wrev)
 		}
 		}
-		if !reflect.DeepEqual(kvs, tt.wkvs) {
-			t.Errorf("#%d: kvs = %+v, want %+v", i, kvs, tt.wkvs)
+		if !reflect.DeepEqual(r.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 {
-			t.Errorf("#%d: rev = %d, want %d", i, rev, tt.wrev)
+		if r.Rev != tt.wrev {
+			t.Errorf("#%d: rev = %d, want %d", i, r.Rev, tt.wrev)
 		}
 		}
-		if !reflect.DeepEqual(kvs, tt.wkvs) {
-			t.Errorf("#%d: kvs = %+v, want %+v", i, kvs, tt.wkvs)
+		if !reflect.DeepEqual(r.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) {
-			t.Errorf("#%d: kvs = %+v, want %+v", i, kvs, tt.wkvs)
+		if !reflect.DeepEqual(r.KVs, tt.wkvs) {
+			t.Errorf("#%d: kvs = %+v, want %+v", i, r.KVs, tt.wkvs)
 		}
 		}
-		if rev != wrev {
-			t.Errorf("#%d: rev = %d, want %d", i, rev, wrev)
+		if r.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) {
-			t.Errorf("#%d: kvs = %+v, want %+v", i, kvs, wkvs)
+		if !reflect.DeepEqual(r.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) {
-			t.Errorf("#%d: kvs = %+v, want %+v", i, kvs, wkvs)
+		if !reflect.DeepEqual(r.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 {
-			t.Errorf("#%d: kvs = %+v, want %+v", i, kvs, nil)
+		if r.KVs != nil {
+			t.Errorf("#%d: kvs = %+v, want %+v", i, r.KVs, nil)
 		}
 		}
-		if rev != base+2 {
-			t.Errorf("#%d: range rev = %d, want %d", i, rev, base+2)
+		if r.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) {
-			t.Errorf("#%d: kvs = %+v, want %+v", i, kvs, wkvs)
+		if !reflect.DeepEqual(r.KVs, wkvs) {
+			t.Errorf("#%d: kvs = %+v, want %+v", i, r.KVs, wkvs)
 		}
 		}
-		if rev != base+1 {
-			t.Errorf("#%d: range rev = %d, want %d", i, rev, base+1)
+		if r.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 {
-			t.Errorf("#%d: kvs = %+v, want %+v", i, kvs, nil)
+		if r.KVs != nil {
+			t.Errorf("#%d: kvs = %+v, want %+v", i, r.KVs, nil)
 		}
 		}
-		if rev != base+1 {
-			t.Errorf("#%d: range rev = %d, want %d", i, rev, base+1)
+		if r.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) {
-			t.Errorf("#%d: kvs = %+v, want %+v", i, kvs, tt.wkvs)
+		if !reflect.DeepEqual(r.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)
-			kvss = append(kvss, kvs)
+			r, _ := s.Range([]byte("a"), []byte("z"), RangeOptions{Rev: k})
+			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)
-			nkvss = append(nkvss, nkvs)
+			r, _ := ns.Range([]byte("a"), []byte("z"), RangeOptions{Rev: k})
+			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) {
-		t.Errorf("kvs = %+v, want %+v", kvs, wkvs)
+	if !reflect.DeepEqual(r.KVs, wkvs) {
+		t.Errorf("kvs = %+v, want %+v", r.KVs, wkvs)
 	}
 	}
-	if rev != 4 {
-		t.Errorf("rev = %d, want %d", rev, 4)
+	if r.Rev != 4 {
+		t.Errorf("rev = %d, want %d", r.Rev, 4)
 	}
 	}
 }
 }
 
 

+ 28 - 11
mvcc/kvstore.go

@@ -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
+	}
+
+	kvs, count, rev, err := s.rangeKeys(key, end, ro.Limit, ro.Rev, ro.Count)
+
+	r = &RangeResult{
+		KVs:   kvs,
+		Count: count,
+		Rev:   rev,
 	}
 	}
-	return s.rangeKeys(key, end, limit, rangeRev)
+	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) {

+ 2 - 2
mvcc/kvstore_test.go

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