Add querynode plugin (#23599)

Signed-off-by: chasingegg <chao.gao@zilliz.com>
pull/23682/head
Gao 2023-04-25 10:40:34 +08:00 committed by GitHub
parent 88bef1b1a6
commit e820479b56
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
29 changed files with 551 additions and 1592 deletions

1
go.mod
View File

@ -36,7 +36,6 @@ require (
github.com/pkg/errors v0.9.1
github.com/prometheus/client_golang v1.11.1
github.com/quasilyte/go-ruleguard/dsl v0.3.21
github.com/sandertv/go-formula/v2 v2.0.0-alpha.7
github.com/sbinet/npyio v0.6.0
github.com/shirou/gopsutil/v3 v3.22.9
github.com/spaolacci/murmur3 v1.1.0

2
go.sum
View File

@ -619,8 +619,6 @@ github.com/ruudk/golang-pdf417 v0.0.0-20181029194003-1af4ab5afa58/go.mod h1:6lfF
github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts=
github.com/samber/lo v1.27.0 h1:GOyDWxsblvqYobqsmUuMddPa2/mMzkKyojlXol4+LaQ=
github.com/samber/lo v1.27.0/go.mod h1:it33p9UtPMS7z72fP4gw/EIfQB2eI8ke7GR2wc6+Rhg=
github.com/sandertv/go-formula/v2 v2.0.0-alpha.7 h1:j6ZnqcpnlGG9oBdhfiGgQ4aQAHEKsMlePvOfD+y5O6s=
github.com/sandertv/go-formula/v2 v2.0.0-alpha.7/go.mod h1:Ag4V2fiOHWXct3SraXNN3dFzFtyu9vqBfrjfYWMGLhE=
github.com/sanity-io/litter v1.2.0/go.mod h1:JF6pZUFgu2Q0sBZ+HSV35P8TVPI1TTzEwyu9FXAw2W4=
github.com/santhosh-tekuri/jsonschema/v5 v5.0.0/go.mod h1:FKdcjfQW6rpZSnxxUvEA5H/cDPdvJ/SZJQLWWXWGrZ0=
github.com/sbinet/npyio v0.6.0 h1:IyqqQIzRjDym9xnIXsToCKei/qCzxDP+Y74KoMlMgXo=

View File

@ -76,6 +76,10 @@ const (
)
const (
TopKKey = "topk"
SearchParamKey = "search_param"
SegmentNumKey = "segment_num"
IndexParamsKey = "params"
IndexTypeKey = "index_type"
MetricTypeKey = "metric_type"

View File

@ -283,6 +283,7 @@ message SearchRequest {
repeated int64 segmentIDs = 3;
bool from_shard_leader = 4;
DataScope scope = 5; // All, Streaming, Historical
int32 total_channel_num = 6;
}
message QueryRequest {

View File

@ -1953,6 +1953,7 @@ type SearchRequest struct {
SegmentIDs []int64 `protobuf:"varint,3,rep,packed,name=segmentIDs,proto3" json:"segmentIDs,omitempty"`
FromShardLeader bool `protobuf:"varint,4,opt,name=from_shard_leader,json=fromShardLeader,proto3" json:"from_shard_leader,omitempty"`
Scope DataScope `protobuf:"varint,5,opt,name=scope,proto3,enum=milvus.proto.query.DataScope" json:"scope,omitempty"`
TotalChannelNum int32 `protobuf:"varint,6,opt,name=total_channel_num,json=totalChannelNum,proto3" json:"total_channel_num,omitempty"`
XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"`
XXX_sizecache int32 `json:"-"`
@ -2018,6 +2019,13 @@ func (m *SearchRequest) GetScope() DataScope {
return DataScope_UnKnown
}
func (m *SearchRequest) GetTotalChannelNum() int32 {
if m != nil {
return m.TotalChannelNum
}
return 0
}
type QueryRequest struct {
Req *internalpb.RetrieveRequest `protobuf:"bytes,1,opt,name=req,proto3" json:"req,omitempty"`
DmlChannels []string `protobuf:"bytes,2,rep,name=dml_channels,json=dmlChannels,proto3" json:"dml_channels,omitempty"`
@ -4087,267 +4095,269 @@ func init() {
func init() { proto.RegisterFile("query_coord.proto", fileDescriptor_aab7cc9a69ed26e8) }
var fileDescriptor_aab7cc9a69ed26e8 = []byte{
// 4155 bytes of a gzipped FileDescriptorProto
// 4178 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xec, 0x3b, 0x49, 0x6c, 0x24, 0x59,
0x56, 0x15, 0xb9, 0xd8, 0x99, 0x2f, 0x17, 0xa7, 0xbf, 0x97, 0xca, 0xc9, 0xa9, 0xc5, 0x1d, 0xd5,
0xd5, 0x6d, 0xdc, 0xdd, 0x76, 0x8f, 0x6b, 0xa6, 0xa9, 0xd9, 0x34, 0x54, 0xd9, 0x53, 0x6e, 0xd3,
0x55, 0x6e, 0x13, 0xae, 0xaa, 0x41, 0xad, 0x66, 0x72, 0x22, 0x33, 0x7e, 0xa6, 0x43, 0x15, 0x19,
0x91, 0x15, 0x11, 0x69, 0xb7, 0x1b, 0x89, 0x13, 0x97, 0x41, 0x80, 0x04, 0x07, 0x4e, 0x88, 0x03,
0x02, 0x09, 0x24, 0x5a, 0xe2, 0x00, 0x37, 0x0e, 0x48, 0x48, 0x70, 0x02, 0x71, 0xe3, 0xc8, 0x15,
0x09, 0x24, 0x04, 0xd2, 0x68, 0x34, 0x37, 0xf4, 0xb7, 0xc8, 0xf8, 0x11, 0x3f, 0x9c, 0x61, 0xbb,
0xb7, 0x41, 0x73, 0x8b, 0x78, 0x7f, 0x79, 0xef, 0xbf, 0xfd, 0xfd, 0x05, 0x16, 0x5f, 0x4e, 0xb0,
0x7f, 0xd6, 0xed, 0x7b, 0x9e, 0x6f, 0x6d, 0x8e, 0x7d, 0x2f, 0xf4, 0x10, 0x1a, 0xd9, 0xce, 0xc9,
0x24, 0x60, 0x7f, 0x9b, 0xb4, 0xbd, 0x53, 0xef, 0x7b, 0xa3, 0x91, 0xe7, 0x32, 0x58, 0xa7, 0x1e,
0xef, 0xd1, 0x69, 0xda, 0x6e, 0x88, 0x7d, 0xd7, 0x74, 0x44, 0x6b, 0xd0, 0x3f, 0xc6, 0x23, 0x93,
0xff, 0xb5, 0x2c, 0x33, 0x34, 0xe3, 0xf3, 0xeb, 0xbf, 0xad, 0xc1, 0xea, 0xd1, 0xb1, 0x77, 0xba,
0xe3, 0x39, 0x0e, 0xee, 0x87, 0xb6, 0xe7, 0x06, 0x06, 0x7e, 0x39, 0xc1, 0x41, 0x88, 0xde, 0x86,
0x52, 0xcf, 0x0c, 0x70, 0x5b, 0x5b, 0xd3, 0xd6, 0x6b, 0xdb, 0x37, 0x36, 0x25, 0x4a, 0x38, 0x09,
0x4f, 0x82, 0xe1, 0x43, 0x33, 0xc0, 0x06, 0xed, 0x89, 0x10, 0x94, 0xac, 0xde, 0xfe, 0x6e, 0xbb,
0xb0, 0xa6, 0xad, 0x17, 0x0d, 0xfa, 0x8d, 0x5e, 0x85, 0x46, 0x3f, 0x9a, 0x7b, 0x7f, 0x37, 0x68,
0x17, 0xd7, 0x8a, 0xeb, 0x45, 0x43, 0x06, 0xea, 0xff, 0xae, 0xc1, 0xf5, 0x14, 0x19, 0xc1, 0xd8,
0x73, 0x03, 0x8c, 0xee, 0xc1, 0x5c, 0x10, 0x9a, 0xe1, 0x24, 0xe0, 0x94, 0x7c, 0x55, 0x49, 0xc9,
0x11, 0xed, 0x62, 0xf0, 0xae, 0x69, 0xb4, 0x05, 0x05, 0x5a, 0xf4, 0x35, 0x58, 0xb6, 0xdd, 0x27,
0x78, 0xe4, 0xf9, 0x67, 0xdd, 0x31, 0xf6, 0xfb, 0xd8, 0x0d, 0xcd, 0x21, 0x16, 0x34, 0x2e, 0x89,
0xb6, 0xc3, 0x69, 0x13, 0x7a, 0x07, 0xae, 0x33, 0x29, 0x05, 0xd8, 0x3f, 0xb1, 0xfb, 0xb8, 0x6b,
0x9e, 0x98, 0xb6, 0x63, 0xf6, 0x1c, 0xdc, 0x2e, 0xad, 0x15, 0xd7, 0x2b, 0xc6, 0x0a, 0x6d, 0x3e,
0x62, 0xad, 0x0f, 0x44, 0xa3, 0xfe, 0xe7, 0x1a, 0xac, 0x90, 0x15, 0x1e, 0x9a, 0x7e, 0x68, 0x7f,
0x06, 0x7c, 0xd6, 0xa1, 0x1e, 0x5f, 0x5b, 0xbb, 0x48, 0xdb, 0x24, 0x18, 0xe9, 0x33, 0x16, 0xe8,
0x09, 0x4f, 0x4a, 0x74, 0x99, 0x12, 0x4c, 0xff, 0x33, 0xae, 0x10, 0x71, 0x3a, 0xaf, 0x22, 0x88,
0x24, 0xce, 0x42, 0x1a, 0xe7, 0x25, 0xc4, 0xa0, 0xff, 0x73, 0x11, 0x56, 0x1e, 0x7b, 0xa6, 0x35,
0x55, 0x98, 0xcf, 0x9f, 0x9d, 0xdf, 0x85, 0x39, 0x66, 0x5d, 0xed, 0x12, 0xc5, 0x75, 0x57, 0xc6,
0xc5, 0x2d, 0x6f, 0x4a, 0xe1, 0x11, 0x05, 0x18, 0x7c, 0x10, 0xba, 0x0b, 0x4d, 0x1f, 0x8f, 0x1d,
0xbb, 0x6f, 0x76, 0xdd, 0xc9, 0xa8, 0x87, 0xfd, 0x76, 0x79, 0x4d, 0x5b, 0x2f, 0x1b, 0x0d, 0x0e,
0x3d, 0xa0, 0x40, 0xf4, 0x23, 0x68, 0x0c, 0x6c, 0xec, 0x58, 0x5d, 0xdb, 0xb5, 0xf0, 0x47, 0xfb,
0xbb, 0xed, 0xb9, 0xb5, 0xe2, 0x7a, 0x6d, 0xfb, 0xdb, 0x9b, 0x69, 0xcf, 0xb0, 0xa9, 0xe4, 0xc8,
0xe6, 0x23, 0x32, 0x7c, 0x9f, 0x8d, 0xfe, 0xbe, 0x1b, 0xfa, 0x67, 0x46, 0x7d, 0x10, 0x03, 0xa1,
0x36, 0xcc, 0xfb, 0x78, 0xe0, 0xe3, 0xe0, 0xb8, 0x3d, 0xbf, 0xa6, 0xad, 0x57, 0x0c, 0xf1, 0x8b,
0x5e, 0x87, 0x05, 0x1f, 0x07, 0xde, 0xc4, 0xef, 0xe3, 0xee, 0xd0, 0xf7, 0x26, 0xe3, 0xa0, 0x5d,
0x59, 0x2b, 0xae, 0x57, 0x8d, 0xa6, 0x00, 0xef, 0x51, 0x68, 0xe7, 0x7b, 0xb0, 0x98, 0xc2, 0x82,
0x5a, 0x50, 0x7c, 0x81, 0xcf, 0xa8, 0x20, 0x8a, 0x06, 0xf9, 0x44, 0xcb, 0x50, 0x3e, 0x31, 0x9d,
0x09, 0xe6, 0xac, 0x66, 0x3f, 0xdf, 0x2a, 0xdc, 0xd7, 0xf4, 0x3f, 0xd6, 0xa0, 0x6d, 0x60, 0x07,
0x9b, 0x01, 0xfe, 0x22, 0x45, 0xba, 0x0a, 0x73, 0xae, 0x67, 0xe1, 0xfd, 0x5d, 0x2a, 0xd2, 0xa2,
0xc1, 0xff, 0xf4, 0x9f, 0x69, 0xb0, 0xbc, 0x87, 0x43, 0xa2, 0xdb, 0x76, 0x10, 0xda, 0xfd, 0xc8,
0x78, 0xbf, 0x0b, 0x45, 0x1f, 0xbf, 0xe4, 0x94, 0xbd, 0x21, 0x53, 0x16, 0xb9, 0x62, 0xd5, 0x48,
0x83, 0x8c, 0x43, 0xaf, 0x40, 0xdd, 0x1a, 0x39, 0xdd, 0xfe, 0xb1, 0xe9, 0xba, 0xd8, 0x61, 0xd6,
0x51, 0x35, 0x6a, 0xd6, 0xc8, 0xd9, 0xe1, 0x20, 0x74, 0x0b, 0x20, 0xc0, 0xc3, 0x11, 0x76, 0xc3,
0xa9, 0xf7, 0x8c, 0x41, 0xd0, 0x06, 0x2c, 0x0e, 0x7c, 0x6f, 0xd4, 0x0d, 0x8e, 0x4d, 0xdf, 0xea,
0x3a, 0xd8, 0xb4, 0xb0, 0x4f, 0xa9, 0xaf, 0x18, 0x0b, 0xa4, 0xe1, 0x88, 0xc0, 0x1f, 0x53, 0x30,
0xba, 0x07, 0xe5, 0xa0, 0xef, 0x8d, 0x31, 0xd5, 0xb4, 0xe6, 0xf6, 0x4d, 0x95, 0x0e, 0xed, 0x9a,
0xa1, 0x79, 0x44, 0x3a, 0x19, 0xac, 0xaf, 0xfe, 0x3f, 0xdc, 0xd4, 0xbe, 0xe4, 0x9e, 0x2b, 0x66,
0x8e, 0xe5, 0x4f, 0xc7, 0x1c, 0xe7, 0x72, 0x99, 0xe3, 0xfc, 0xf9, 0xe6, 0x98, 0xe2, 0xda, 0x45,
0xcc, 0xb1, 0x32, 0xd3, 0x1c, 0xab, 0x9f, 0x8d, 0x39, 0xfe, 0xfd, 0xd4, 0x1c, 0xbf, 0xec, 0x62,
0x9f, 0x9a, 0x6c, 0x59, 0x32, 0xd9, 0xbf, 0xd4, 0xe0, 0x2b, 0x7b, 0x38, 0x8c, 0xc8, 0x27, 0x16,
0x88, 0xbf, 0xa4, 0x41, 0xf7, 0x13, 0x0d, 0x3a, 0x2a, 0x5a, 0xaf, 0x12, 0x78, 0x3f, 0x80, 0xd5,
0x08, 0x47, 0xd7, 0xc2, 0x41, 0xdf, 0xb7, 0xc7, 0x54, 0x8c, 0xd4, 0xc9, 0xd4, 0xb6, 0xef, 0xa8,
0x34, 0x36, 0x49, 0xc1, 0x4a, 0x34, 0xc5, 0x6e, 0x6c, 0x06, 0xfd, 0xf7, 0x34, 0x58, 0x21, 0x4e,
0x8d, 0x7b, 0x21, 0x77, 0xe0, 0x5d, 0x9e, 0xaf, 0xb2, 0x7f, 0x2b, 0xa4, 0xfc, 0x5b, 0x0e, 0x1e,
0xd3, 0x2c, 0x36, 0x49, 0xcf, 0x55, 0x78, 0xf7, 0x0d, 0x28, 0xdb, 0xee, 0xc0, 0x13, 0xac, 0xba,
0xad, 0x62, 0x55, 0x1c, 0x19, 0xeb, 0xad, 0xbb, 0x8c, 0x8a, 0xa9, 0xc3, 0xbd, 0x82, 0xba, 0x25,
0x97, 0x5d, 0x50, 0x2c, 0xfb, 0x77, 0x35, 0xb8, 0x9e, 0x42, 0x78, 0x95, 0x75, 0x7f, 0x07, 0xe6,
0x68, 0x18, 0x11, 0x0b, 0x7f, 0x55, 0xb9, 0xf0, 0x18, 0xba, 0xc7, 0x76, 0x10, 0x1a, 0x7c, 0x8c,
0xee, 0x41, 0x2b, 0xd9, 0x46, 0x02, 0x1c, 0x0f, 0x6e, 0x5d, 0xd7, 0x1c, 0x31, 0x06, 0x54, 0x8d,
0x1a, 0x87, 0x1d, 0x98, 0x23, 0x8c, 0xbe, 0x02, 0x15, 0x62, 0xb2, 0x5d, 0xdb, 0x12, 0xe2, 0x9f,
0xa7, 0x26, 0x6c, 0x05, 0xe8, 0x26, 0x00, 0x6d, 0x32, 0x2d, 0xcb, 0x67, 0xb1, 0xaf, 0x6a, 0x54,
0x09, 0xe4, 0x01, 0x01, 0xe8, 0x7f, 0xa0, 0x41, 0x9d, 0xf8, 0xd8, 0x27, 0x38, 0x34, 0x89, 0x1c,
0xd0, 0x37, 0xa1, 0xea, 0x78, 0xa6, 0xd5, 0x0d, 0xcf, 0xc6, 0x0c, 0x55, 0x33, 0xc9, 0xeb, 0xa9,
0x63, 0x7e, 0x7a, 0x36, 0xc6, 0x46, 0xc5, 0xe1, 0x5f, 0x79, 0xf8, 0x9d, 0x32, 0xe5, 0xa2, 0xc2,
0x94, 0xff, 0xb1, 0x0c, 0xab, 0x3f, 0x30, 0xc3, 0xfe, 0xf1, 0xee, 0x48, 0x84, 0xf0, 0xcb, 0x2b,
0xc1, 0xd4, 0xb7, 0x15, 0xe2, 0xbe, 0xed, 0x53, 0xf3, 0x9d, 0x91, 0x9e, 0x97, 0x55, 0x7a, 0x4e,
0x8a, 0xc5, 0xcd, 0xe7, 0x5c, 0x54, 0x31, 0x3d, 0x8f, 0x45, 0xda, 0xb9, 0xcb, 0x44, 0xda, 0x1d,
0x68, 0xe0, 0x8f, 0xfa, 0xce, 0x84, 0xc8, 0x9c, 0x62, 0x67, 0x21, 0xf4, 0x96, 0x02, 0x7b, 0xdc,
0xc8, 0xea, 0x7c, 0xd0, 0x3e, 0xa7, 0x81, 0x89, 0x7a, 0x84, 0x43, 0x93, 0xc6, 0xc9, 0xda, 0xf6,
0x5a, 0x96, 0xa8, 0x85, 0x7e, 0x30, 0x71, 0x93, 0x3f, 0x74, 0x03, 0xaa, 0x3c, 0xae, 0xef, 0xef,
0xb6, 0xab, 0x94, 0x7d, 0x53, 0x00, 0x32, 0xa1, 0xc1, 0x3d, 0x10, 0xa7, 0x10, 0x28, 0x85, 0xdf,
0x51, 0x21, 0x50, 0x0b, 0x3b, 0x4e, 0x79, 0xc0, 0xa3, 0x7c, 0x10, 0x03, 0x91, 0x02, 0xd5, 0x1b,
0x0c, 0x1c, 0xdb, 0xc5, 0x07, 0x4c, 0xc2, 0x35, 0x4a, 0x84, 0x0c, 0x24, 0xb9, 0xc0, 0x09, 0xf6,
0x03, 0xdb, 0x73, 0xdb, 0x75, 0xda, 0x2e, 0x7e, 0x3b, 0x5d, 0x58, 0x4c, 0xa1, 0x50, 0x84, 0xf8,
0xaf, 0xc7, 0x43, 0xfc, 0x6c, 0x1e, 0xc7, 0x52, 0x80, 0xbf, 0xd0, 0x60, 0xe5, 0x99, 0x1b, 0x4c,
0x7a, 0xd1, 0xda, 0xbe, 0x18, 0x3d, 0x4e, 0x7a, 0x90, 0x52, 0xca, 0x83, 0xe8, 0x3f, 0x2e, 0xc3,
0x02, 0x5f, 0x05, 0x11, 0x37, 0x75, 0x05, 0x37, 0xa0, 0x1a, 0x05, 0x11, 0xce, 0x90, 0x29, 0x00,
0xad, 0x41, 0x2d, 0x66, 0x08, 0x9c, 0xaa, 0x38, 0x28, 0x17, 0x69, 0x22, 0x25, 0x28, 0xc5, 0x52,
0x82, 0x9b, 0x00, 0x03, 0x67, 0x12, 0x1c, 0x77, 0x43, 0x7b, 0x84, 0x79, 0x4a, 0x52, 0xa5, 0x90,
0xa7, 0xf6, 0x08, 0xa3, 0x07, 0x50, 0xef, 0xd9, 0xae, 0xe3, 0x0d, 0xbb, 0x63, 0x33, 0x3c, 0x0e,
0x78, 0x31, 0xa7, 0x12, 0x0b, 0x4d, 0xe0, 0x1e, 0xd2, 0xbe, 0x46, 0x8d, 0x8d, 0x39, 0x24, 0x43,
0xd0, 0x2d, 0xa8, 0xb9, 0x93, 0x51, 0xd7, 0x1b, 0x74, 0x7d, 0xef, 0x34, 0xa0, 0x25, 0x5b, 0xd1,
0xa8, 0xba, 0x93, 0xd1, 0xfb, 0x03, 0xc3, 0x3b, 0x25, 0x4e, 0xbc, 0x4a, 0xdc, 0x79, 0xe0, 0x78,
0x43, 0x56, 0xae, 0xcd, 0x9e, 0x7f, 0x3a, 0x80, 0x8c, 0xb6, 0xb0, 0x13, 0x9a, 0x74, 0x74, 0x35,
0xdf, 0xe8, 0x68, 0x00, 0x7a, 0x0d, 0x9a, 0x7d, 0x6f, 0x34, 0x36, 0x29, 0x87, 0x1e, 0xf9, 0xde,
0x88, 0x5a, 0x4e, 0xd1, 0x48, 0x40, 0xd1, 0x0e, 0xd4, 0x68, 0xfe, 0xcc, 0xcd, 0xab, 0x46, 0xf1,
0xe8, 0x2a, 0xf3, 0x8a, 0xe5, 0xb1, 0x44, 0x41, 0xc1, 0x16, 0x9f, 0x01, 0xd1, 0x0c, 0x61, 0xa5,
0x81, 0xfd, 0x31, 0xe6, 0x16, 0x52, 0xe3, 0xb0, 0x23, 0xfb, 0x63, 0x4c, 0x92, 0x7a, 0xdb, 0x0d,
0xb0, 0x1f, 0x8a, 0x12, 0xab, 0xdd, 0xa0, 0xea, 0xd3, 0x60, 0x50, 0xae, 0xd8, 0x68, 0x1f, 0x9a,
0x41, 0x68, 0xfa, 0x61, 0x77, 0xec, 0x05, 0x54, 0x01, 0xda, 0x4d, 0xaa, 0xdb, 0x7a, 0x46, 0x41,
0xf7, 0x24, 0x18, 0x1e, 0xf2, 0x9e, 0x46, 0x83, 0x8e, 0x14, 0xbf, 0xfa, 0x7f, 0x17, 0xa0, 0x29,
0xd3, 0x4c, 0x8c, 0x98, 0x25, 0xf8, 0x42, 0x11, 0xc5, 0x2f, 0x59, 0x01, 0x76, 0xcd, 0x9e, 0x83,
0x59, 0x35, 0x41, 0xf5, 0xb0, 0x62, 0xd4, 0x18, 0x8c, 0x4e, 0x40, 0xf4, 0x89, 0x71, 0x8a, 0x2a,
0x7f, 0x91, 0x52, 0x5f, 0xa5, 0x10, 0x1a, 0x3c, 0xdb, 0x30, 0x2f, 0x0a, 0x11, 0xa6, 0x85, 0xe2,
0x97, 0xb4, 0xf4, 0x26, 0x36, 0xc5, 0xca, 0xb4, 0x50, 0xfc, 0xa2, 0x5d, 0xa8, 0xb3, 0x29, 0xc7,
0xa6, 0x6f, 0x8e, 0x84, 0x0e, 0xbe, 0xa2, 0xb4, 0xe3, 0xf7, 0xf0, 0xd9, 0x73, 0xe2, 0x12, 0x0e,
0x4d, 0xdb, 0x37, 0x98, 0xcc, 0x0e, 0xe9, 0x28, 0xb4, 0x0e, 0x2d, 0x36, 0xcb, 0xc0, 0x76, 0x30,
0xd7, 0xe6, 0x79, 0x56, 0x8d, 0x50, 0xf8, 0x23, 0xdb, 0xc1, 0x4c, 0x61, 0xa3, 0x25, 0x50, 0x29,
0x55, 0x98, 0xbe, 0x52, 0x08, 0x95, 0xd1, 0x1d, 0x68, 0xb0, 0x66, 0xe1, 0xe9, 0x98, 0x3b, 0x66,
0x34, 0x3e, 0x67, 0x30, 0x9a, 0x24, 0x4c, 0x46, 0x4c, 0xe3, 0x81, 0x2d, 0xc7, 0x9d, 0x8c, 0x88,
0xbe, 0xeb, 0x7f, 0x58, 0x82, 0x25, 0x62, 0xf6, 0xdc, 0x03, 0x5c, 0x21, 0xdc, 0xde, 0x04, 0xb0,
0x82, 0xb0, 0x2b, 0xb9, 0xaa, 0xaa, 0x15, 0x84, 0xdc, 0x19, 0x7f, 0x53, 0x44, 0xcb, 0x62, 0x76,
0x02, 0x9d, 0x70, 0x43, 0xe9, 0x88, 0x79, 0xa9, 0xad, 0xa2, 0x3b, 0xd0, 0xe0, 0x65, 0x9f, 0x54,
0xea, 0xd4, 0x19, 0xf0, 0x40, 0xed, 0x4c, 0xe7, 0x94, 0x5b, 0x56, 0xb1, 0xa8, 0x39, 0x7f, 0xb5,
0xa8, 0x59, 0x49, 0x46, 0xcd, 0xf7, 0x60, 0x81, 0x7a, 0x82, 0xc8, 0x8a, 0x84, 0x03, 0xc9, 0x63,
0x46, 0x4d, 0x3a, 0x54, 0xfc, 0x06, 0xf1, 0xc8, 0x07, 0x52, 0xe4, 0x23, 0xcc, 0x70, 0x31, 0xb6,
0xba, 0xa1, 0x6f, 0xba, 0xc1, 0x00, 0xfb, 0x34, 0x72, 0x56, 0x8c, 0x3a, 0x01, 0x3e, 0xe5, 0x30,
0xfd, 0x5f, 0x0a, 0xb0, 0xca, 0x0b, 0xd8, 0xab, 0xeb, 0x45, 0x56, 0xf8, 0x12, 0xfe, 0xbf, 0x78,
0x4e, 0x49, 0x58, 0xca, 0x91, 0x9a, 0x95, 0x15, 0xa9, 0x99, 0x5c, 0x16, 0xcd, 0xa5, 0xca, 0xa2,
0x68, 0x2b, 0x67, 0x3e, 0xff, 0x56, 0x0e, 0x29, 0xf8, 0x69, 0xae, 0x4e, 0x65, 0x57, 0x35, 0xd8,
0x4f, 0x3e, 0x86, 0xfe, 0xa7, 0x06, 0x8d, 0x23, 0x6c, 0xfa, 0xfd, 0x63, 0xc1, 0xc7, 0x77, 0xe2,
0x5b, 0x5f, 0xaf, 0x66, 0x88, 0x58, 0x1a, 0xf2, 0xf3, 0xb3, 0xe7, 0xf5, 0x5f, 0x1a, 0xd4, 0x7f,
0x8d, 0x34, 0x89, 0xc5, 0xde, 0x8f, 0x2f, 0xf6, 0xb5, 0x8c, 0xc5, 0x1a, 0x38, 0xf4, 0x6d, 0x7c,
0x82, 0x7f, 0xee, 0x96, 0xfb, 0x4f, 0x1a, 0x74, 0x8e, 0xce, 0xdc, 0xbe, 0xc1, 0x6c, 0xf9, 0xea,
0x16, 0x73, 0x07, 0x1a, 0x27, 0x52, 0xd6, 0x56, 0xa0, 0x0a, 0x57, 0x3f, 0x89, 0x17, 0x7e, 0x06,
0xb4, 0xc4, 0x8e, 0x1b, 0x5f, 0xac, 0x70, 0xad, 0xaf, 0xab, 0xa8, 0x4e, 0x10, 0x47, 0x5d, 0xd3,
0x82, 0x2f, 0x03, 0xf5, 0xdf, 0xd7, 0x60, 0x49, 0xd1, 0x11, 0x5d, 0x87, 0x79, 0x5e, 0x64, 0xf2,
0x18, 0xcc, 0x6c, 0xd8, 0x22, 0xe2, 0x99, 0x6e, 0x93, 0xd8, 0x56, 0x3a, 0x15, 0xb4, 0xd0, 0x6d,
0xa8, 0x45, 0xd5, 0x80, 0x95, 0x92, 0x8f, 0x15, 0xa0, 0x0e, 0x54, 0xb8, 0x73, 0x12, 0x65, 0x56,
0xf4, 0xaf, 0xff, 0x9d, 0x06, 0xab, 0xef, 0x9a, 0xae, 0xe5, 0x0d, 0x06, 0x57, 0x67, 0xeb, 0x0e,
0x48, 0x45, 0x44, 0xde, 0xed, 0x09, 0xb9, 0xf2, 0x78, 0x03, 0x16, 0x7d, 0xe6, 0x19, 0x2d, 0x99,
0xef, 0x45, 0xa3, 0x25, 0x1a, 0x22, 0x7e, 0xfe, 0x55, 0x01, 0x10, 0x09, 0x06, 0x0f, 0x4d, 0xc7,
0x74, 0xfb, 0xf8, 0xf2, 0xa4, 0xdf, 0x85, 0xa6, 0x14, 0xc2, 0xa2, 0x13, 0xb9, 0x78, 0x0c, 0x0b,
0xd0, 0x7b, 0xd0, 0xec, 0x31, 0x54, 0x5d, 0x1f, 0x9b, 0x81, 0xe7, 0x52, 0xe7, 0xda, 0x54, 0xef,
0x44, 0x3c, 0xf5, 0xed, 0xe1, 0x10, 0xfb, 0x3b, 0x9e, 0x6b, 0xf1, 0x5c, 0xac, 0x27, 0xc8, 0x24,
0x43, 0x89, 0xe0, 0xa6, 0xf1, 0x5c, 0x88, 0x06, 0xa2, 0x80, 0x4e, 0x59, 0x11, 0x60, 0xd3, 0x99,
0x32, 0x62, 0xea, 0x8d, 0x5b, 0xac, 0xe1, 0x28, 0x7b, 0x23, 0x4a, 0x11, 0x5f, 0xf5, 0xbf, 0xd1,
0x00, 0x45, 0xf5, 0x12, 0xad, 0x0c, 0xa9, 0xf6, 0x25, 0x87, 0x6a, 0x8a, 0xa0, 0x70, 0x03, 0xaa,
0x96, 0x18, 0xc9, 0xcd, 0x65, 0x0a, 0xa0, 0x3e, 0x9a, 0x12, 0xdd, 0x25, 0xc1, 0x18, 0x5b, 0xa2,
0x1e, 0x61, 0xc0, 0xc7, 0x14, 0x26, 0x87, 0xe7, 0x52, 0x32, 0x3c, 0xc7, 0xf7, 0x59, 0xca, 0xd2,
0x3e, 0x8b, 0xfe, 0x49, 0x01, 0x5a, 0xd4, 0xdd, 0xed, 0x4c, 0x8b, 0xfd, 0x5c, 0x44, 0xdf, 0x81,
0x06, 0x3f, 0xb3, 0x96, 0x08, 0xaf, 0xbf, 0x8c, 0x4d, 0x86, 0xde, 0x86, 0x65, 0xd6, 0xc9, 0xc7,
0xc1, 0xc4, 0x99, 0xa6, 0xe2, 0x2c, 0x99, 0x45, 0x2f, 0x99, 0x9f, 0x25, 0x4d, 0x62, 0xc4, 0x33,
0x58, 0x1d, 0x3a, 0x5e, 0xcf, 0x74, 0xba, 0xb2, 0x78, 0x98, 0x0c, 0x73, 0x68, 0xfc, 0x32, 0x1b,
0x7e, 0x14, 0x97, 0x61, 0x80, 0xf6, 0x48, 0x59, 0x8f, 0x5f, 0x4c, 0xb3, 0xfc, 0x72, 0xee, 0x2c,
0xbf, 0x4e, 0x06, 0x46, 0x49, 0xfe, 0x9f, 0x68, 0xb0, 0x90, 0xd8, 0x2a, 0x4d, 0x96, 0x94, 0x5a,
0xba, 0xa4, 0xbc, 0x0f, 0x65, 0x52, 0x67, 0x31, 0x67, 0xd8, 0x54, 0x97, 0x3b, 0xf2, 0xac, 0x06,
0x1b, 0x80, 0xb6, 0x60, 0x49, 0x71, 0x40, 0xca, 0x75, 0x00, 0xa5, 0xcf, 0x47, 0xf5, 0x9f, 0x94,
0xa0, 0x16, 0xe3, 0xc7, 0x8c, 0x6a, 0x38, 0xcf, 0xde, 0x57, 0x62, 0x79, 0xc5, 0xf4, 0xf2, 0x32,
0xce, 0xce, 0x88, 0xde, 0x8d, 0xf0, 0x88, 0x25, 0xff, 0xbc, 0x12, 0x19, 0xe1, 0x11, 0x4d, 0xfd,
0xe3, 0x59, 0xfd, 0x9c, 0x94, 0xd5, 0x27, 0xea, 0x9e, 0xf9, 0x73, 0xea, 0x9e, 0x8a, 0x5c, 0xf7,
0x48, 0x76, 0x54, 0x4d, 0xda, 0x51, 0xde, 0x02, 0xf5, 0x6d, 0x58, 0xea, 0xfb, 0xd8, 0x0c, 0xb1,
0xf5, 0xf0, 0x6c, 0x27, 0x6a, 0xe2, 0x99, 0x91, 0xaa, 0x09, 0x3d, 0x9a, 0xee, 0x19, 0x31, 0x29,
0xd7, 0xa9, 0x94, 0xd5, 0x65, 0x15, 0x97, 0x0d, 0x13, 0xb2, 0x70, 0xcf, 0xf4, 0x2f, 0x59, 0x1a,
0x37, 0x2e, 0x55, 0x1a, 0xdf, 0x86, 0x9a, 0x08, 0xad, 0xc4, 0xdc, 0x9b, 0xcc, 0xf3, 0x09, 0x5f,
0x60, 0x05, 0x92, 0x33, 0x58, 0x90, 0x37, 0x5d, 0x93, 0x45, 0x69, 0x2b, 0x5d, 0x94, 0x5e, 0x87,
0x79, 0x3b, 0xe8, 0x0e, 0xcc, 0x17, 0xb8, 0xbd, 0x48, 0x5b, 0xe7, 0xec, 0xe0, 0x91, 0xf9, 0x02,
0xeb, 0xff, 0x5a, 0x84, 0xe6, 0xb4, 0x8a, 0xc9, 0xed, 0x46, 0xf2, 0x5c, 0x12, 0x38, 0x80, 0xd6,
0x34, 0x50, 0x53, 0x0e, 0x9f, 0x5b, 0x88, 0x25, 0x4f, 0x32, 0x16, 0xc6, 0x09, 0x7b, 0x95, 0xf6,
0x8a, 0x4b, 0x17, 0xda, 0x2b, 0xbe, 0xe2, 0x49, 0xe3, 0x3d, 0x58, 0x89, 0x02, 0xb0, 0xb4, 0x6c,
0x96, 0xe5, 0x2f, 0x8b, 0xc6, 0xc3, 0xf8, 0xf2, 0x33, 0x5c, 0xc0, 0x7c, 0x96, 0x0b, 0x48, 0xaa,
0x40, 0x25, 0xa5, 0x02, 0xe9, 0x03, 0xcf, 0xaa, 0xe2, 0xc0, 0x53, 0x7f, 0x06, 0x4b, 0x74, 0x1b,
0x30, 0xe8, 0xfb, 0x76, 0x0f, 0x47, 0x39, 0x6b, 0x1e, 0xb1, 0x76, 0xa0, 0x92, 0x48, 0x7b, 0xa3,
0x7f, 0xfd, 0x77, 0x34, 0x58, 0x4d, 0xcf, 0x4b, 0x35, 0x66, 0xea, 0x48, 0x34, 0xc9, 0x91, 0xfc,
0x3a, 0x2c, 0x4d, 0xa7, 0x97, 0x13, 0xea, 0x8c, 0x94, 0x51, 0x41, 0xb8, 0x81, 0xa6, 0x73, 0x08,
0x98, 0xfe, 0x13, 0x2d, 0xda, 0x4d, 0x25, 0xb0, 0x21, 0xdd, 0x63, 0x26, 0xc1, 0xcd, 0x73, 0x1d,
0xdb, 0x8d, 0xaa, 0x6e, 0xbe, 0x46, 0x06, 0xe4, 0x55, 0xf7, 0xbb, 0xb0, 0xc0, 0x3b, 0x45, 0x31,
0x2a, 0x67, 0x56, 0xd6, 0x64, 0xe3, 0xa2, 0xe8, 0x74, 0x17, 0x9a, 0x7c, 0xf3, 0x57, 0xe0, 0x2b,
0xaa, 0xb6, 0x84, 0x7f, 0x15, 0x5a, 0xa2, 0xdb, 0x45, 0xa3, 0xe2, 0x02, 0x1f, 0x18, 0x65, 0x77,
0x3f, 0xd6, 0xa0, 0x2d, 0xc7, 0xc8, 0xd8, 0xf2, 0x2f, 0x9e, 0xe3, 0x7d, 0x5b, 0x3e, 0x36, 0xbb,
0x7b, 0x0e, 0x3d, 0x53, 0x3c, 0xe2, 0xf0, 0xec, 0x80, 0x1e, 0x81, 0x92, 0xd2, 0x64, 0xd7, 0x0e,
0x42, 0xdf, 0xee, 0x4d, 0xae, 0x74, 0x05, 0x44, 0xff, 0xdb, 0x02, 0x7c, 0x55, 0x39, 0xe1, 0x55,
0x0e, 0xc8, 0xb2, 0x76, 0x02, 0x1e, 0x42, 0x25, 0x51, 0xc2, 0xbc, 0x76, 0xce, 0xe2, 0xf9, 0xa6,
0x16, 0xdb, 0x5c, 0x11, 0xe3, 0xc8, 0x1c, 0x91, 0x4e, 0x97, 0xb2, 0xe7, 0xe0, 0x4a, 0x2b, 0xcd,
0x21, 0xc6, 0xa1, 0x07, 0x50, 0x67, 0xe5, 0x61, 0xf7, 0xc4, 0xc6, 0xa7, 0xe2, 0x5c, 0xe7, 0x96,
0xd2, 0xaf, 0xd1, 0x7e, 0xcf, 0x6d, 0x7c, 0x6a, 0xd4, 0x9c, 0xe8, 0x3b, 0xd0, 0xff, 0xb7, 0x08,
0x30, 0x6d, 0x23, 0xb5, 0xe9, 0xd4, 0x60, 0xb8, 0x05, 0xc4, 0x20, 0x24, 0x10, 0xcb, 0xb9, 0x9f,
0xf8, 0x45, 0xc6, 0x74, 0x7b, 0xd6, 0xb2, 0x83, 0x90, 0xf3, 0x65, 0xeb, 0x7c, 0x5a, 0x04, 0x8b,
0x88, 0xc8, 0xd8, 0xb1, 0x89, 0xa8, 0xbd, 0x08, 0x04, 0xbd, 0x05, 0x68, 0xe8, 0x7b, 0xa7, 0xb6,
0x3b, 0x8c, 0x67, 0xec, 0x2c, 0xb1, 0x5f, 0xe4, 0x2d, 0xb1, 0x94, 0xfd, 0x87, 0xd0, 0x4a, 0x74,
0x17, 0x2c, 0xb9, 0x37, 0x83, 0x8c, 0x3d, 0x69, 0x2e, 0x7e, 0x82, 0xb3, 0x20, 0x63, 0x08, 0x3a,
0x5d, 0x68, 0x25, 0xe9, 0x55, 0x9c, 0xc1, 0x7c, 0x43, 0x3e, 0x83, 0x39, 0xcf, 0x4c, 0xc9, 0x34,
0xb1, 0x43, 0x98, 0xce, 0x00, 0x96, 0x55, 0x94, 0x28, 0x90, 0xdc, 0x97, 0x91, 0xe4, 0xc9, 0x69,
0x63, 0x87, 0x3d, 0xdf, 0x8b, 0xd2, 0x45, 0xca, 0xe6, 0x2c, 0x0f, 0x1c, 0xdb, 0x94, 0x2b, 0x48,
0x9b, 0x72, 0xfa, 0x1f, 0x69, 0x80, 0xd2, 0xda, 0x8d, 0x9a, 0x50, 0x88, 0x26, 0x29, 0xec, 0xef,
0x26, 0xb4, 0xa9, 0x90, 0xd2, 0xa6, 0x1b, 0x50, 0x8d, 0x22, 0x22, 0x77, 0x7f, 0x53, 0x40, 0x5c,
0xd7, 0x4a, 0xb2, 0xae, 0xc5, 0x08, 0x2b, 0xcb, 0x84, 0x1d, 0x03, 0x4a, 0x5b, 0x4c, 0x7c, 0x26,
0x4d, 0x9e, 0x69, 0x16, 0x85, 0x31, 0x4c, 0x45, 0x19, 0xd3, 0x7f, 0x14, 0x00, 0x4d, 0x63, 0x7e,
0x74, 0x10, 0x95, 0x27, 0x50, 0x6e, 0xc1, 0x52, 0x3a, 0x23, 0x10, 0x69, 0x10, 0x4a, 0xe5, 0x03,
0xaa, 0xd8, 0x5d, 0x54, 0x5d, 0x56, 0x7a, 0x27, 0xf2, 0x71, 0x2c, 0xc1, 0xb9, 0x95, 0x95, 0xe0,
0x24, 0xdc, 0xdc, 0x6f, 0x24, 0x2f, 0x39, 0x31, 0xa3, 0xb9, 0xaf, 0xf4, 0x47, 0xa9, 0x25, 0xcf,
0xba, 0xe1, 0x74, 0xf5, 0xeb, 0x49, 0xff, 0x56, 0x80, 0xc5, 0x88, 0x1b, 0x17, 0xe2, 0xf4, 0xec,
0x83, 0xbf, 0xcf, 0x98, 0xb5, 0x1f, 0xaa, 0x59, 0xfb, 0xcb, 0xe7, 0xe6, 0xb0, 0x9f, 0x1f, 0x67,
0x3f, 0x86, 0x79, 0xbe, 0x7d, 0x96, 0xb2, 0xdd, 0x3c, 0x55, 0xe2, 0x32, 0x94, 0x89, 0xab, 0x10,
0xfb, 0x49, 0xec, 0x87, 0xb1, 0x34, 0x7e, 0x6f, 0x8d, 0x9b, 0x6f, 0x43, 0xba, 0xb6, 0xa6, 0xff,
0xb5, 0x06, 0x70, 0x74, 0xe6, 0xf6, 0x1f, 0x30, 0x4b, 0x7b, 0x1b, 0x4a, 0xb3, 0xee, 0x71, 0x90,
0xde, 0x34, 0x37, 0xa7, 0x3d, 0x73, 0x08, 0x57, 0xaa, 0x83, 0x8b, 0xc9, 0x3a, 0x38, 0xab, 0x82,
0xcd, 0xf6, 0x2e, 0xff, 0xa0, 0xc1, 0x75, 0x42, 0xc4, 0xa7, 0x92, 0xb2, 0xe4, 0xe2, 0x70, 0xcc,
0x73, 0x15, 0x65, 0xcf, 0x75, 0x1f, 0xe6, 0x59, 0x29, 0x2a, 0xd2, 0x87, 0x5b, 0x59, 0x2c, 0x63,
0x0c, 0x36, 0x44, 0x77, 0xfd, 0x19, 0x34, 0x8c, 0xb8, 0x24, 0x10, 0x82, 0x52, 0xec, 0xb6, 0x0e,
0xfd, 0xa6, 0xc9, 0xbc, 0x39, 0x36, 0xfb, 0x76, 0x78, 0x46, 0x09, 0x2b, 0x1b, 0xd1, 0xbf, 0x5a,
0xec, 0xfa, 0x4f, 0x35, 0x58, 0x15, 0xe7, 0x07, 0x5c, 0xa9, 0x2e, 0xcf, 0x9b, 0x6d, 0x58, 0xe1,
0x1a, 0x94, 0x50, 0x25, 0x96, 0x75, 0x2c, 0x31, 0x98, 0xbc, 0x8c, 0x6d, 0x58, 0x09, 0x4d, 0x7f,
0x88, 0xc3, 0xe4, 0x18, 0xc6, 0xb9, 0x25, 0xd6, 0x28, 0x8f, 0xc9, 0x73, 0x7e, 0x73, 0x9b, 0x9d,
0xc0, 0x73, 0x87, 0xc0, 0x75, 0x02, 0xdc, 0xc9, 0x88, 0xaf, 0x52, 0x3f, 0x85, 0x1b, 0xec, 0xbe,
0x5c, 0x4f, 0xa6, 0xe8, 0x4a, 0xdb, 0xa7, 0xca, 0x75, 0x27, 0x4c, 0xe8, 0x4f, 0x35, 0xb8, 0x99,
0x81, 0xf9, 0x2a, 0x69, 0xef, 0x63, 0x25, 0xf6, 0x8c, 0x0c, 0x5f, 0xc2, 0x4b, 0xf3, 0xd3, 0x04,
0x91, 0x3f, 0x2b, 0xc1, 0x62, 0xaa, 0xd3, 0x85, 0x75, 0xee, 0x4d, 0x40, 0x44, 0x08, 0xd1, 0xf3,
0x0b, 0x5a, 0x34, 0x71, 0x5f, 0xdd, 0x72, 0x27, 0xa3, 0xe8, 0xe9, 0x05, 0xa9, 0x9b, 0x90, 0xcd,
0x7a, 0xb3, 0xcd, 0xd3, 0x48, 0x72, 0xa5, 0xec, 0xbb, 0xbb, 0x29, 0x02, 0x37, 0x0f, 0x26, 0x23,
0xb6, 0xcf, 0xca, 0xa5, 0xcc, 0xfc, 0x2f, 0x41, 0x25, 0x81, 0xd1, 0x00, 0x16, 0xe9, 0xfd, 0x8c,
0x49, 0x38, 0xf4, 0x48, 0xe6, 0x49, 0xe9, 0x62, 0x5e, 0xfe, 0x5b, 0xb9, 0x31, 0xbd, 0xcf, 0x47,
0x13, 0xe2, 0x79, 0xf2, 0xe9, 0xca, 0x50, 0x81, 0xc7, 0x76, 0xfb, 0xde, 0x28, 0xc2, 0x33, 0x77,
0x41, 0x3c, 0xfb, 0x7c, 0xb4, 0x8c, 0x27, 0x0e, 0xed, 0xec, 0xc0, 0x8a, 0x72, 0xe9, 0xb3, 0xe2,
0x4a, 0x39, 0x9e, 0xc8, 0x3e, 0x84, 0x65, 0xd5, 0xaa, 0x2e, 0x31, 0x47, 0x8a, 0xe2, 0x8b, 0xcc,
0xb1, 0xf1, 0x2b, 0x50, 0x8d, 0x4e, 0xbf, 0x50, 0x0d, 0xe6, 0x9f, 0xb9, 0xef, 0xb9, 0xde, 0xa9,
0xdb, 0xba, 0x86, 0xe6, 0xa1, 0xf8, 0xc0, 0x71, 0x5a, 0x1a, 0x6a, 0x40, 0xf5, 0x28, 0xf4, 0xb1,
0x49, 0x90, 0xb4, 0x0a, 0xa8, 0x09, 0xf0, 0xae, 0x1d, 0x84, 0x9e, 0x6f, 0xf7, 0x4d, 0xa7, 0x55,
0xdc, 0xf8, 0x18, 0x9a, 0xf2, 0xde, 0x12, 0xaa, 0x43, 0xe5, 0xc0, 0x0b, 0xbf, 0xff, 0x91, 0x1d,
0x84, 0xad, 0x6b, 0xa4, 0xff, 0x81, 0x17, 0x1e, 0xfa, 0x38, 0xc0, 0x6e, 0xd8, 0xd2, 0x10, 0xc0,
0xdc, 0xfb, 0xee, 0xae, 0x1d, 0xbc, 0x68, 0x15, 0xd0, 0x12, 0xdf, 0x36, 0x36, 0x9d, 0x7d, 0xbe,
0x61, 0xd3, 0x2a, 0x92, 0xe1, 0xd1, 0x5f, 0x09, 0xb5, 0xa0, 0x1e, 0x75, 0xd9, 0x3b, 0x7c, 0xd6,
0x2a, 0xa3, 0x2a, 0x94, 0xd9, 0xe7, 0xdc, 0x86, 0x05, 0xad, 0xe4, 0x99, 0x07, 0x99, 0x93, 0x2d,
0x22, 0x02, 0xb5, 0xae, 0x91, 0x95, 0xf1, 0x43, 0xa7, 0x96, 0x86, 0x16, 0xa0, 0x16, 0x3b, 0xc2,
0x69, 0x15, 0x08, 0x60, 0xcf, 0x1f, 0xf7, 0xb9, 0x37, 0x62, 0x24, 0x10, 0x76, 0xee, 0x12, 0x4e,
0x94, 0x36, 0x1e, 0x42, 0x45, 0x6c, 0x7a, 0x91, 0xae, 0x9c, 0x45, 0xe4, 0xb7, 0x75, 0x0d, 0x2d,
0x42, 0x43, 0xba, 0xd6, 0xde, 0xd2, 0x10, 0x82, 0xa6, 0xfc, 0xf0, 0xa4, 0x55, 0xd8, 0xd8, 0x06,
0x98, 0x26, 0x3f, 0x84, 0x9c, 0x7d, 0xf7, 0xc4, 0x74, 0x6c, 0x8b, 0xd1, 0x46, 0x9a, 0x08, 0x77,
0x29, 0x77, 0x98, 0x66, 0xb5, 0x0a, 0x1b, 0xb7, 0xa1, 0x22, 0x02, 0x3a, 0x81, 0x1b, 0x78, 0xe4,
0x9d, 0x60, 0x26, 0x99, 0x23, 0x1c, 0xb6, 0xb4, 0xed, 0x9f, 0x22, 0x00, 0x76, 0x4c, 0xe1, 0x79,
0xbe, 0x85, 0x1c, 0x40, 0x7b, 0x38, 0xdc, 0xf1, 0x46, 0x63, 0xcf, 0x15, 0xdb, 0xa7, 0x01, 0xda,
0x94, 0x75, 0x9f, 0xff, 0xa4, 0x3b, 0xf2, 0xd5, 0x77, 0x5e, 0x55, 0xf6, 0x4f, 0x74, 0xd6, 0xaf,
0xa1, 0x11, 0xc5, 0xf6, 0xd4, 0x1e, 0xe1, 0xa7, 0x76, 0xff, 0x45, 0x74, 0xb6, 0x91, 0xfd, 0xe4,
0x23, 0xd1, 0x55, 0xe0, 0xbb, 0xa3, 0xc4, 0x77, 0x14, 0xfa, 0xb6, 0x3b, 0x14, 0x5e, 0x5a, 0xbf,
0x86, 0x5e, 0x26, 0x1e, 0x9c, 0x08, 0x84, 0xdb, 0x79, 0xde, 0x98, 0x5c, 0x0e, 0xa5, 0x03, 0x0b,
0x89, 0x37, 0x78, 0x68, 0x43, 0x7d, 0x01, 0x58, 0xf5, 0x5e, 0xb0, 0xf3, 0x46, 0xae, 0xbe, 0x11,
0x36, 0x1b, 0x9a, 0xf2, 0x3b, 0x33, 0xf4, 0x4b, 0x59, 0x13, 0xa4, 0x9e, 0x20, 0x74, 0x36, 0xf2,
0x74, 0x8d, 0x50, 0x7d, 0xc0, 0x14, 0x74, 0x16, 0x2a, 0xe5, 0x73, 0x8d, 0xce, 0x79, 0x01, 0x52,
0xbf, 0x86, 0x7e, 0x44, 0x62, 0x59, 0xe2, 0xa1, 0x04, 0x7a, 0x53, 0xed, 0x7f, 0xd5, 0xef, 0x29,
0x66, 0x61, 0xf8, 0x20, 0x69, 0x5e, 0xd9, 0xd4, 0xa7, 0x9e, 0x4e, 0xe5, 0xa7, 0x3e, 0x36, 0xfd,
0x79, 0xd4, 0x5f, 0x18, 0xc3, 0x84, 0x9a, 0x4d, 0xf2, 0xb0, 0xec, 0x2d, 0x15, 0x8a, 0xcc, 0xd7,
0x1a, 0x9d, 0xcd, 0xbc, 0xdd, 0xe3, 0xda, 0x25, 0x3f, 0x08, 0x50, 0x33, 0x4d, 0xf9, 0x88, 0x41,
0xad, 0x5d, 0xea, 0xf7, 0x05, 0xfa, 0x35, 0xf4, 0x54, 0x72, 0xaf, 0xe8, 0xb5, 0x2c, 0xe1, 0xc8,
0x47, 0xe8, 0xb3, 0xf8, 0xf6, 0x9b, 0x80, 0x98, 0xed, 0xb8, 0x03, 0x7b, 0x38, 0xf1, 0x4d, 0xa6,
0x58, 0x59, 0xee, 0x26, 0xdd, 0x55, 0xa0, 0xf9, 0xda, 0x05, 0x46, 0x44, 0x4b, 0xea, 0x02, 0xec,
0xe1, 0xf0, 0x09, 0x0e, 0x7d, 0xbb, 0x1f, 0x24, 0x57, 0x34, 0xf5, 0xa8, 0xbc, 0x83, 0x40, 0xf5,
0xfa, 0xcc, 0x7e, 0x11, 0x82, 0x1e, 0xd4, 0xf6, 0x48, 0xe6, 0x4d, 0xb3, 0x89, 0x00, 0x65, 0x8e,
0x14, 0x3d, 0x04, 0x8a, 0xf5, 0xd9, 0x1d, 0xe3, 0xee, 0x2c, 0xf1, 0x38, 0x02, 0x65, 0x0a, 0x36,
0xfd, 0x64, 0x43, 0xed, 0xce, 0x32, 0x5e, 0x5b, 0xb0, 0x15, 0xed, 0x1c, 0xe3, 0xfe, 0x8b, 0x77,
0xb1, 0xe9, 0x84, 0xc7, 0x19, 0x2b, 0x8a, 0xf5, 0x38, 0x7f, 0x45, 0x52, 0xc7, 0x08, 0x07, 0x86,
0xa5, 0x1d, 0x7a, 0xf2, 0x28, 0x97, 0x2c, 0x5b, 0xea, 0x29, 0xd2, 0x3d, 0x73, 0xaa, 0x9e, 0x09,
0x8b, 0xbb, 0xbe, 0x37, 0x96, 0x91, 0xbc, 0xa5, 0x44, 0x92, 0xea, 0x97, 0x13, 0xc5, 0x0f, 0xa0,
0x2e, 0x2a, 0x43, 0x9a, 0xcb, 0xaa, 0xb9, 0x10, 0xef, 0x92, 0x73, 0xe2, 0x0f, 0x61, 0x21, 0x51,
0x72, 0xaa, 0x85, 0xae, 0xae, 0x4b, 0x67, 0xcd, 0x7e, 0x0a, 0x88, 0xbe, 0x78, 0x91, 0x5e, 0xdb,
0x65, 0x64, 0x1c, 0xe9, 0x8e, 0x02, 0xc9, 0x56, 0xee, 0xfe, 0x91, 0xe4, 0x7f, 0x0b, 0x56, 0x94,
0x65, 0x5d, 0xd2, 0x21, 0xf0, 0xfb, 0x5d, 0xe7, 0xd4, 0x9e, 0x49, 0x87, 0x70, 0xee, 0x08, 0x81,
0x7f, 0xfb, 0x93, 0x26, 0x54, 0x69, 0xe6, 0x45, 0xa5, 0xf5, 0x8b, 0xc4, 0xeb, 0xd3, 0x4d, 0xbc,
0x3e, 0x84, 0x85, 0xc4, 0x2b, 0x12, 0xb5, 0xd2, 0xaa, 0x9f, 0x9a, 0xe4, 0xc8, 0x1f, 0xe4, 0x77,
0x1c, 0xea, 0x50, 0xa8, 0x7c, 0xeb, 0x31, 0x6b, 0xee, 0xe7, 0xec, 0x01, 0x56, 0x74, 0x86, 0xf9,
0x7a, 0xe6, 0x2e, 0xa8, 0x7c, 0xf7, 0xed, 0x8b, 0xcf, 0x4b, 0x3e, 0xfb, 0xbc, 0xed, 0x43, 0x58,
0x48, 0xdc, 0x40, 0x56, 0x4b, 0x55, 0x7d, 0x4d, 0x79, 0xd6, 0xec, 0x9f, 0x63, 0x82, 0x63, 0xc1,
0x92, 0xe2, 0x72, 0x28, 0xda, 0xcc, 0xda, 0x5e, 0x54, 0xdf, 0x22, 0x9d, 0xbd, 0xa0, 0x86, 0x64,
0x4a, 0xc9, 0x98, 0x30, 0x25, 0x32, 0xf9, 0x94, 0xbe, 0xf3, 0x66, 0xbe, 0x77, 0xf7, 0xd1, 0x82,
0x8e, 0x60, 0x8e, 0xdd, 0x4b, 0x46, 0xaf, 0xa8, 0xcf, 0xe2, 0x62, 0x77, 0x96, 0x3b, 0xb3, 0x6e,
0x36, 0x07, 0x13, 0x27, 0x0c, 0xe8, 0xa4, 0x65, 0xea, 0x21, 0x91, 0xf2, 0x42, 0x7d, 0xfc, 0x32,
0x71, 0x67, 0xf6, 0xfd, 0x61, 0x31, 0xe9, 0xff, 0xef, 0x2c, 0xf0, 0x23, 0x58, 0x52, 0x9c, 0xd0,
0xa3, 0xac, 0x6c, 0x3f, 0xe3, 0x6e, 0x40, 0x67, 0x2b, 0x77, 0xff, 0x08, 0xf3, 0x0f, 0xa1, 0x95,
0xdc, 0xb6, 0x47, 0x6f, 0x64, 0xe9, 0xb3, 0x0a, 0xe7, 0xf9, 0xca, 0xfc, 0xf0, 0xeb, 0x1f, 0x6c,
0x0f, 0xed, 0xf0, 0x78, 0xd2, 0x23, 0x2d, 0x5b, 0xac, 0xeb, 0x5b, 0xb6, 0xc7, 0xbf, 0xb6, 0x04,
0xff, 0xb7, 0xe8, 0xe8, 0x2d, 0x8a, 0x6a, 0xdc, 0xeb, 0xcd, 0xd1, 0xdf, 0x7b, 0xff, 0x17, 0x00,
0x00, 0xff, 0xff, 0xc2, 0xde, 0x60, 0xae, 0x08, 0x48, 0x00, 0x00,
0x56, 0x15, 0xb9, 0xd8, 0x99, 0x2f, 0x17, 0xa7, 0xbf, 0xcb, 0x55, 0x39, 0x39, 0xb5, 0xb8, 0xa3,
0xba, 0xba, 0x4d, 0x75, 0xb7, 0xdd, 0xe3, 0x9a, 0x69, 0x6a, 0x36, 0x0d, 0x55, 0xf6, 0x94, 0xdb,
0x74, 0x95, 0xbb, 0x08, 0x57, 0xd5, 0xa0, 0x56, 0x33, 0x39, 0x91, 0x19, 0x3f, 0xd3, 0xa1, 0x8a,
0x25, 0x2b, 0x22, 0xd2, 0x6e, 0x37, 0x12, 0x27, 0x2e, 0x83, 0x00, 0x09, 0x0e, 0x70, 0x41, 0x1c,
0x10, 0x48, 0x20, 0xd1, 0x12, 0x07, 0xb8, 0x71, 0x40, 0x42, 0x82, 0x13, 0x88, 0x1b, 0x47, 0xae,
0x1c, 0x90, 0x10, 0x48, 0xa3, 0xd1, 0xdc, 0xd0, 0xdf, 0x22, 0xe3, 0x47, 0xfc, 0x70, 0x86, 0xed,
0xde, 0x06, 0xcd, 0x2d, 0xe2, 0xfd, 0xe5, 0xbd, 0xff, 0xf6, 0xf7, 0x17, 0x58, 0x7e, 0x39, 0xc5,
0xc1, 0x49, 0x7f, 0xe8, 0xfb, 0x81, 0xb5, 0x31, 0x09, 0xfc, 0xc8, 0x47, 0xc8, 0xb5, 0x9d, 0xa3,
0x69, 0xc8, 0xfe, 0x36, 0x68, 0x7b, 0xaf, 0x39, 0xf4, 0x5d, 0xd7, 0xf7, 0x18, 0xac, 0xd7, 0x4c,
0xf6, 0xe8, 0xb5, 0x6d, 0x2f, 0xc2, 0x81, 0x67, 0x3a, 0xa2, 0x35, 0x1c, 0x1e, 0x62, 0xd7, 0xe4,
0x7f, 0x1d, 0xcb, 0x8c, 0xcc, 0xe4, 0xfc, 0xfa, 0x6f, 0x6b, 0x70, 0xe5, 0xe0, 0xd0, 0x3f, 0xde,
0xf6, 0x1d, 0x07, 0x0f, 0x23, 0xdb, 0xf7, 0x42, 0x03, 0xbf, 0x9c, 0xe2, 0x30, 0x42, 0x6f, 0x43,
0x65, 0x60, 0x86, 0xb8, 0xab, 0xad, 0x69, 0xeb, 0x8d, 0xad, 0x6b, 0x1b, 0x12, 0x25, 0x9c, 0x84,
0xc7, 0xe1, 0xf8, 0x81, 0x19, 0x62, 0x83, 0xf6, 0x44, 0x08, 0x2a, 0xd6, 0x60, 0x6f, 0xa7, 0x5b,
0x5a, 0xd3, 0xd6, 0xcb, 0x06, 0xfd, 0x46, 0xaf, 0x42, 0x6b, 0x18, 0xcf, 0xbd, 0xb7, 0x13, 0x76,
0xcb, 0x6b, 0xe5, 0xf5, 0xb2, 0x21, 0x03, 0xf5, 0xff, 0xd0, 0xe0, 0x6a, 0x86, 0x8c, 0x70, 0xe2,
0x7b, 0x21, 0x46, 0x77, 0x61, 0x21, 0x8c, 0xcc, 0x68, 0x1a, 0x72, 0x4a, 0xbe, 0xaa, 0xa4, 0xe4,
0x80, 0x76, 0x31, 0x78, 0xd7, 0x2c, 0xda, 0x92, 0x02, 0x2d, 0xfa, 0x1a, 0x5c, 0xb6, 0xbd, 0xc7,
0xd8, 0xf5, 0x83, 0x93, 0xfe, 0x04, 0x07, 0x43, 0xec, 0x45, 0xe6, 0x18, 0x0b, 0x1a, 0x57, 0x44,
0xdb, 0x93, 0x59, 0x13, 0x7a, 0x07, 0xae, 0x32, 0x29, 0x85, 0x38, 0x38, 0xb2, 0x87, 0xb8, 0x6f,
0x1e, 0x99, 0xb6, 0x63, 0x0e, 0x1c, 0xdc, 0xad, 0xac, 0x95, 0xd7, 0x6b, 0xc6, 0x2a, 0x6d, 0x3e,
0x60, 0xad, 0xf7, 0x45, 0xa3, 0xfe, 0x17, 0x1a, 0xac, 0x92, 0x15, 0x3e, 0x31, 0x83, 0xc8, 0xfe,
0x0c, 0xf8, 0xac, 0x43, 0x33, 0xb9, 0xb6, 0x6e, 0x99, 0xb6, 0x49, 0x30, 0xd2, 0x67, 0x22, 0xd0,
0x13, 0x9e, 0x54, 0xe8, 0x32, 0x25, 0x98, 0xfe, 0xe7, 0x5c, 0x21, 0x92, 0x74, 0x5e, 0x44, 0x10,
0x69, 0x9c, 0xa5, 0x2c, 0xce, 0x73, 0x88, 0x41, 0xff, 0x97, 0x32, 0xac, 0x3e, 0xf2, 0x4d, 0x6b,
0xa6, 0x30, 0x9f, 0x3f, 0x3b, 0xbf, 0x0b, 0x0b, 0xcc, 0xba, 0xba, 0x15, 0x8a, 0xeb, 0xb6, 0x8c,
0x8b, 0x5b, 0xde, 0x8c, 0xc2, 0x03, 0x0a, 0x30, 0xf8, 0x20, 0x74, 0x1b, 0xda, 0x01, 0x9e, 0x38,
0xf6, 0xd0, 0xec, 0x7b, 0x53, 0x77, 0x80, 0x83, 0x6e, 0x75, 0x4d, 0x5b, 0xaf, 0x1a, 0x2d, 0x0e,
0xdd, 0xa7, 0x40, 0xf4, 0x23, 0x68, 0x8d, 0x6c, 0xec, 0x58, 0x7d, 0xdb, 0xb3, 0xf0, 0x47, 0x7b,
0x3b, 0xdd, 0x85, 0xb5, 0xf2, 0x7a, 0x63, 0xeb, 0xdb, 0x1b, 0x59, 0xcf, 0xb0, 0xa1, 0xe4, 0xc8,
0xc6, 0x43, 0x32, 0x7c, 0x8f, 0x8d, 0xfe, 0xbe, 0x17, 0x05, 0x27, 0x46, 0x73, 0x94, 0x00, 0xa1,
0x2e, 0x2c, 0x06, 0x78, 0x14, 0xe0, 0xf0, 0xb0, 0xbb, 0xb8, 0xa6, 0xad, 0xd7, 0x0c, 0xf1, 0x8b,
0x5e, 0x87, 0xa5, 0x00, 0x87, 0xfe, 0x34, 0x18, 0xe2, 0xfe, 0x38, 0xf0, 0xa7, 0x93, 0xb0, 0x5b,
0x5b, 0x2b, 0xaf, 0xd7, 0x8d, 0xb6, 0x00, 0xef, 0x52, 0x68, 0xef, 0x7b, 0xb0, 0x9c, 0xc1, 0x82,
0x3a, 0x50, 0x7e, 0x81, 0x4f, 0xa8, 0x20, 0xca, 0x06, 0xf9, 0x44, 0x97, 0xa1, 0x7a, 0x64, 0x3a,
0x53, 0xcc, 0x59, 0xcd, 0x7e, 0xbe, 0x55, 0xba, 0xa7, 0xe9, 0x7f, 0xa2, 0x41, 0xd7, 0xc0, 0x0e,
0x36, 0x43, 0xfc, 0x45, 0x8a, 0xf4, 0x0a, 0x2c, 0x78, 0xbe, 0x85, 0xf7, 0x76, 0xa8, 0x48, 0xcb,
0x06, 0xff, 0xd3, 0x7f, 0xa6, 0xc1, 0xe5, 0x5d, 0x1c, 0x11, 0xdd, 0xb6, 0xc3, 0xc8, 0x1e, 0xc6,
0xc6, 0xfb, 0x5d, 0x28, 0x07, 0xf8, 0x25, 0xa7, 0xec, 0x0d, 0x99, 0xb2, 0xd8, 0x15, 0xab, 0x46,
0x1a, 0x64, 0x1c, 0x7a, 0x05, 0x9a, 0x96, 0xeb, 0xf4, 0x87, 0x87, 0xa6, 0xe7, 0x61, 0x87, 0x59,
0x47, 0xdd, 0x68, 0x58, 0xae, 0xb3, 0xcd, 0x41, 0xe8, 0x06, 0x40, 0x88, 0xc7, 0x2e, 0xf6, 0xa2,
0x99, 0xf7, 0x4c, 0x40, 0xd0, 0x1d, 0x58, 0x1e, 0x05, 0xbe, 0xdb, 0x0f, 0x0f, 0xcd, 0xc0, 0xea,
0x3b, 0xd8, 0xb4, 0x70, 0x40, 0xa9, 0xaf, 0x19, 0x4b, 0xa4, 0xe1, 0x80, 0xc0, 0x1f, 0x51, 0x30,
0xba, 0x0b, 0xd5, 0x70, 0xe8, 0x4f, 0x30, 0xd5, 0xb4, 0xf6, 0xd6, 0x75, 0x95, 0x0e, 0xed, 0x98,
0x91, 0x79, 0x40, 0x3a, 0x19, 0xac, 0xaf, 0xfe, 0x3f, 0xdc, 0xd4, 0xbe, 0xe4, 0x9e, 0x2b, 0x61,
0x8e, 0xd5, 0x4f, 0xc7, 0x1c, 0x17, 0x0a, 0x99, 0xe3, 0xe2, 0xe9, 0xe6, 0x98, 0xe1, 0xda, 0x59,
0xcc, 0xb1, 0x36, 0xd7, 0x1c, 0xeb, 0x9f, 0x8d, 0x39, 0xfe, 0xc3, 0xcc, 0x1c, 0xbf, 0xec, 0x62,
0x9f, 0x99, 0x6c, 0x55, 0x32, 0xd9, 0xbf, 0xd2, 0xe0, 0x2b, 0xbb, 0x38, 0x8a, 0xc9, 0x27, 0x16,
0x88, 0xbf, 0xa4, 0x41, 0xf7, 0x13, 0x0d, 0x7a, 0x2a, 0x5a, 0x2f, 0x12, 0x78, 0x3f, 0x80, 0x2b,
0x31, 0x8e, 0xbe, 0x85, 0xc3, 0x61, 0x60, 0x4f, 0xa8, 0x18, 0xa9, 0x93, 0x69, 0x6c, 0xdd, 0x52,
0x69, 0x6c, 0x9a, 0x82, 0xd5, 0x78, 0x8a, 0x9d, 0xc4, 0x0c, 0xfa, 0xef, 0x69, 0xb0, 0x4a, 0x9c,
0x1a, 0xf7, 0x42, 0xde, 0xc8, 0x3f, 0x3f, 0x5f, 0x65, 0xff, 0x56, 0xca, 0xf8, 0xb7, 0x02, 0x3c,
0xa6, 0x59, 0x6c, 0x9a, 0x9e, 0x8b, 0xf0, 0xee, 0x1b, 0x50, 0xb5, 0xbd, 0x91, 0x2f, 0x58, 0x75,
0x53, 0xc5, 0xaa, 0x24, 0x32, 0xd6, 0x5b, 0xf7, 0x18, 0x15, 0x33, 0x87, 0x7b, 0x01, 0x75, 0x4b,
0x2f, 0xbb, 0xa4, 0x58, 0xf6, 0xef, 0x6a, 0x70, 0x35, 0x83, 0xf0, 0x22, 0xeb, 0xfe, 0x0e, 0x2c,
0xd0, 0x30, 0x22, 0x16, 0xfe, 0xaa, 0x72, 0xe1, 0x09, 0x74, 0x8f, 0xec, 0x30, 0x32, 0xf8, 0x18,
0xdd, 0x87, 0x4e, 0xba, 0x8d, 0x04, 0x38, 0x1e, 0xdc, 0xfa, 0x9e, 0xe9, 0x32, 0x06, 0xd4, 0x8d,
0x06, 0x87, 0xed, 0x9b, 0x2e, 0x46, 0x5f, 0x81, 0x1a, 0x31, 0xd9, 0xbe, 0x6d, 0x09, 0xf1, 0x2f,
0x52, 0x13, 0xb6, 0x42, 0x74, 0x1d, 0x80, 0x36, 0x99, 0x96, 0x15, 0xb0, 0xd8, 0x57, 0x37, 0xea,
0x04, 0x72, 0x9f, 0x00, 0xf4, 0x3f, 0xd0, 0xa0, 0x49, 0x7c, 0xec, 0x63, 0x1c, 0x99, 0x44, 0x0e,
0xe8, 0x9b, 0x50, 0x77, 0x7c, 0xd3, 0xea, 0x47, 0x27, 0x13, 0x86, 0xaa, 0x9d, 0xe6, 0xf5, 0xcc,
0x31, 0x3f, 0x3d, 0x99, 0x60, 0xa3, 0xe6, 0xf0, 0xaf, 0x22, 0xfc, 0xce, 0x98, 0x72, 0x59, 0x61,
0xca, 0xff, 0x54, 0x85, 0x2b, 0x3f, 0x30, 0xa3, 0xe1, 0xe1, 0x8e, 0x2b, 0x42, 0xf8, 0xf9, 0x95,
0x60, 0xe6, 0xdb, 0x4a, 0x49, 0xdf, 0xf6, 0xa9, 0xf9, 0xce, 0x58, 0xcf, 0xab, 0x2a, 0x3d, 0x27,
0xc5, 0xe2, 0xc6, 0x73, 0x2e, 0xaa, 0x84, 0x9e, 0x27, 0x22, 0xed, 0xc2, 0x79, 0x22, 0xed, 0x36,
0xb4, 0xf0, 0x47, 0x43, 0x67, 0x4a, 0x64, 0x4e, 0xb1, 0xb3, 0x10, 0x7a, 0x43, 0x81, 0x3d, 0x69,
0x64, 0x4d, 0x3e, 0x68, 0x8f, 0xd3, 0xc0, 0x44, 0xed, 0xe2, 0xc8, 0xa4, 0x71, 0xb2, 0xb1, 0xb5,
0x96, 0x27, 0x6a, 0xa1, 0x1f, 0x4c, 0xdc, 0xe4, 0x0f, 0x5d, 0x83, 0x3a, 0x8f, 0xeb, 0x7b, 0x3b,
0xdd, 0x3a, 0x65, 0xdf, 0x0c, 0x80, 0x4c, 0x68, 0x71, 0x0f, 0xc4, 0x29, 0x04, 0x4a, 0xe1, 0x77,
0x54, 0x08, 0xd4, 0xc2, 0x4e, 0x52, 0x1e, 0xf2, 0x28, 0x1f, 0x26, 0x40, 0xa4, 0x40, 0xf5, 0x47,
0x23, 0xc7, 0xf6, 0xf0, 0x3e, 0x93, 0x70, 0x83, 0x12, 0x21, 0x03, 0x49, 0x2e, 0x70, 0x84, 0x83,
0xd0, 0xf6, 0xbd, 0x6e, 0x93, 0xb6, 0x8b, 0xdf, 0x5e, 0x1f, 0x96, 0x33, 0x28, 0x14, 0x21, 0xfe,
0xeb, 0xc9, 0x10, 0x3f, 0x9f, 0xc7, 0x89, 0x14, 0xe0, 0x2f, 0x35, 0x58, 0x7d, 0xe6, 0x85, 0xd3,
0x41, 0xbc, 0xb6, 0x2f, 0x46, 0x8f, 0xd3, 0x1e, 0xa4, 0x92, 0xf1, 0x20, 0xfa, 0x8f, 0xab, 0xb0,
0xc4, 0x57, 0x41, 0xc4, 0x4d, 0x5d, 0xc1, 0x35, 0xa8, 0xc7, 0x41, 0x84, 0x33, 0x64, 0x06, 0x40,
0x6b, 0xd0, 0x48, 0x18, 0x02, 0xa7, 0x2a, 0x09, 0x2a, 0x44, 0x9a, 0x48, 0x09, 0x2a, 0x89, 0x94,
0xe0, 0x3a, 0xc0, 0xc8, 0x99, 0x86, 0x87, 0xfd, 0xc8, 0x76, 0x31, 0x4f, 0x49, 0xea, 0x14, 0xf2,
0xd4, 0x76, 0x31, 0xba, 0x0f, 0xcd, 0x81, 0xed, 0x39, 0xfe, 0xb8, 0x3f, 0x31, 0xa3, 0xc3, 0x90,
0x17, 0x73, 0x2a, 0xb1, 0xd0, 0x04, 0xee, 0x01, 0xed, 0x6b, 0x34, 0xd8, 0x98, 0x27, 0x64, 0x08,
0xba, 0x01, 0x0d, 0x6f, 0xea, 0xf6, 0xfd, 0x51, 0x3f, 0xf0, 0x8f, 0x43, 0x5a, 0xb2, 0x95, 0x8d,
0xba, 0x37, 0x75, 0xdf, 0x1f, 0x19, 0xfe, 0x31, 0x71, 0xe2, 0x75, 0xe2, 0xce, 0x43, 0xc7, 0x1f,
0xb3, 0x72, 0x6d, 0xfe, 0xfc, 0xb3, 0x01, 0x64, 0xb4, 0x85, 0x9d, 0xc8, 0xa4, 0xa3, 0xeb, 0xc5,
0x46, 0xc7, 0x03, 0xd0, 0x6b, 0xd0, 0x1e, 0xfa, 0xee, 0xc4, 0xa4, 0x1c, 0x7a, 0x18, 0xf8, 0x2e,
0xb5, 0x9c, 0xb2, 0x91, 0x82, 0xa2, 0x6d, 0x68, 0xd0, 0xfc, 0x99, 0x9b, 0x57, 0x83, 0xe2, 0xd1,
0x55, 0xe6, 0x95, 0xc8, 0x63, 0x89, 0x82, 0x82, 0x2d, 0x3e, 0x43, 0xa2, 0x19, 0xc2, 0x4a, 0x43,
0xfb, 0x63, 0xcc, 0x2d, 0xa4, 0xc1, 0x61, 0x07, 0xf6, 0xc7, 0x98, 0x24, 0xf5, 0xb6, 0x17, 0xe2,
0x20, 0x12, 0x25, 0x56, 0xb7, 0x45, 0xd5, 0xa7, 0xc5, 0xa0, 0x5c, 0xb1, 0xd1, 0x1e, 0xb4, 0xc3,
0xc8, 0x0c, 0xa2, 0xfe, 0xc4, 0x0f, 0xa9, 0x02, 0x74, 0xdb, 0x54, 0xb7, 0xf5, 0x9c, 0x82, 0xee,
0x71, 0x38, 0x7e, 0xc2, 0x7b, 0x1a, 0x2d, 0x3a, 0x52, 0xfc, 0xea, 0xff, 0x5d, 0x82, 0xb6, 0x4c,
0x33, 0x31, 0x62, 0x96, 0xe0, 0x0b, 0x45, 0x14, 0xbf, 0x64, 0x05, 0xd8, 0x33, 0x07, 0x0e, 0x66,
0xd5, 0x04, 0xd5, 0xc3, 0x9a, 0xd1, 0x60, 0x30, 0x3a, 0x01, 0xd1, 0x27, 0xc6, 0x29, 0xaa, 0xfc,
0x65, 0x4a, 0x7d, 0x9d, 0x42, 0x68, 0xf0, 0xec, 0xc2, 0xa2, 0x28, 0x44, 0x98, 0x16, 0x8a, 0x5f,
0xd2, 0x32, 0x98, 0xda, 0x14, 0x2b, 0xd3, 0x42, 0xf1, 0x8b, 0x76, 0xa0, 0xc9, 0xa6, 0x9c, 0x98,
0x81, 0xe9, 0x0a, 0x1d, 0x7c, 0x45, 0x69, 0xc7, 0xef, 0xe1, 0x93, 0xe7, 0xc4, 0x25, 0x3c, 0x31,
0xed, 0xc0, 0x60, 0x32, 0x7b, 0x42, 0x47, 0xa1, 0x75, 0xe8, 0xb0, 0x59, 0x46, 0xb6, 0x83, 0xb9,
0x36, 0x2f, 0xb2, 0x6a, 0x84, 0xc2, 0x1f, 0xda, 0x0e, 0x66, 0x0a, 0x1b, 0x2f, 0x81, 0x4a, 0xa9,
0xc6, 0xf4, 0x95, 0x42, 0xa8, 0x8c, 0x6e, 0x41, 0x8b, 0x35, 0x0b, 0x4f, 0xc7, 0xdc, 0x31, 0xa3,
0xf1, 0x39, 0x83, 0xd1, 0x24, 0x61, 0xea, 0x32, 0x8d, 0x07, 0xb6, 0x1c, 0x6f, 0xea, 0x12, 0x7d,
0xd7, 0xff, 0xb0, 0x02, 0x2b, 0xc4, 0xec, 0xb9, 0x07, 0xb8, 0x40, 0xb8, 0xbd, 0x0e, 0x60, 0x85,
0x51, 0x5f, 0x72, 0x55, 0x75, 0x2b, 0x8c, 0xb8, 0x33, 0xfe, 0xa6, 0x88, 0x96, 0xe5, 0xfc, 0x04,
0x3a, 0xe5, 0x86, 0xb2, 0x11, 0xf3, 0x5c, 0x5b, 0x45, 0xb7, 0xa0, 0xc5, 0xcb, 0x3e, 0xa9, 0xd4,
0x69, 0x32, 0xe0, 0xbe, 0xda, 0x99, 0x2e, 0x28, 0xb7, 0xac, 0x12, 0x51, 0x73, 0xf1, 0x62, 0x51,
0xb3, 0x96, 0x8e, 0x9a, 0xef, 0xc1, 0x12, 0xf5, 0x04, 0xb1, 0x15, 0x09, 0x07, 0x52, 0xc4, 0x8c,
0xda, 0x74, 0xa8, 0xf8, 0x0d, 0x93, 0x91, 0x0f, 0xa4, 0xc8, 0x47, 0x98, 0xe1, 0x61, 0x6c, 0xf5,
0xa3, 0xc0, 0xf4, 0xc2, 0x11, 0x0e, 0x68, 0xe4, 0xac, 0x19, 0x4d, 0x02, 0x7c, 0xca, 0x61, 0xfa,
0xbf, 0x96, 0xe0, 0x0a, 0x2f, 0x60, 0x2f, 0xae, 0x17, 0x79, 0xe1, 0x4b, 0xf8, 0xff, 0xf2, 0x29,
0x25, 0x61, 0xa5, 0x40, 0x6a, 0x56, 0x55, 0xa4, 0x66, 0x72, 0x59, 0xb4, 0x90, 0x29, 0x8b, 0xe2,
0xad, 0x9c, 0xc5, 0xe2, 0x5b, 0x39, 0xa4, 0xe0, 0xa7, 0xb9, 0x3a, 0x95, 0x5d, 0xdd, 0x60, 0x3f,
0xc5, 0x18, 0xfa, 0xc7, 0x25, 0x68, 0x1d, 0x60, 0x33, 0x18, 0x1e, 0x0a, 0x3e, 0xbe, 0x93, 0xdc,
0xfa, 0x7a, 0x35, 0x47, 0xc4, 0xd2, 0x90, 0x9f, 0x9b, 0x3d, 0x2f, 0x82, 0x20, 0xf2, 0x23, 0x33,
0xa6, 0xb2, 0xef, 0x4d, 0x5d, 0xbe, 0x1f, 0xb4, 0x44, 0x1b, 0x38, 0xa9, 0xfb, 0x53, 0x57, 0xff,
0x2f, 0x0d, 0x9a, 0xbf, 0x46, 0xa6, 0x11, 0x8c, 0xb9, 0x97, 0x64, 0xcc, 0x6b, 0x39, 0x8c, 0x31,
0x70, 0x14, 0xd8, 0xf8, 0x08, 0xff, 0xdc, 0x6d, 0x07, 0xfe, 0xb3, 0x06, 0xbd, 0x83, 0x13, 0x6f,
0x68, 0x30, 0xbb, 0xbf, 0xb8, 0x75, 0xdd, 0x82, 0xd6, 0x91, 0x94, 0xe1, 0x95, 0xa8, 0x72, 0x36,
0x8f, 0x92, 0x45, 0xa2, 0x01, 0x1d, 0xb1, 0x3b, 0xc7, 0x17, 0x2b, 0xdc, 0xf0, 0xeb, 0x2a, 0xaa,
0x53, 0xc4, 0x51, 0x37, 0xb6, 0x14, 0xc8, 0x40, 0xfd, 0xf7, 0x35, 0x58, 0x51, 0x74, 0x44, 0x57,
0x61, 0x91, 0x17, 0xa4, 0x3c, 0x5e, 0x33, 0x7b, 0xb7, 0x88, 0x78, 0x66, 0x5b, 0x2a, 0xb6, 0x95,
0x4d, 0x1b, 0x2d, 0x74, 0x13, 0x1a, 0x71, 0xe5, 0x60, 0x65, 0xe4, 0x63, 0x85, 0xa8, 0x07, 0x35,
0xee, 0xc8, 0x44, 0x49, 0x16, 0xff, 0xeb, 0x7f, 0xaf, 0xc1, 0x95, 0x77, 0x4d, 0xcf, 0xf2, 0x47,
0xa3, 0x8b, 0xb3, 0x75, 0x1b, 0xa4, 0x82, 0xa3, 0xe8, 0x56, 0x86, 0x5c, 0xa5, 0xbc, 0x01, 0xcb,
0x01, 0xf3, 0xa2, 0x96, 0xcc, 0xf7, 0xb2, 0xd1, 0x11, 0x0d, 0x31, 0x3f, 0xff, 0xba, 0x04, 0x88,
0x04, 0x8e, 0x07, 0xa6, 0x63, 0x7a, 0x43, 0x7c, 0x7e, 0xd2, 0x6f, 0x43, 0x5b, 0x0a, 0x77, 0xf1,
0xe9, 0x5d, 0x32, 0xde, 0x85, 0xe8, 0x3d, 0x68, 0x0f, 0x18, 0xaa, 0x7e, 0x80, 0xcd, 0xd0, 0xf7,
0xa8, 0x23, 0x6e, 0xab, 0x77, 0x2d, 0x9e, 0x06, 0xf6, 0x78, 0x8c, 0x83, 0x6d, 0xdf, 0xb3, 0x78,
0xde, 0x36, 0x10, 0x64, 0x92, 0xa1, 0x44, 0x70, 0xb3, 0xd8, 0x2f, 0x44, 0x03, 0x71, 0xf0, 0xa7,
0xac, 0x08, 0xb1, 0xe9, 0xcc, 0x18, 0x31, 0xf3, 0xdc, 0x1d, 0xd6, 0x70, 0x90, 0xbf, 0x69, 0xa5,
0x88, 0xc5, 0xfa, 0xdf, 0x6a, 0x80, 0xe2, 0xda, 0x8a, 0x56, 0x91, 0x54, 0xfb, 0xd2, 0x43, 0x35,
0x45, 0x00, 0xb9, 0x06, 0x75, 0x4b, 0x8c, 0xe4, 0xe6, 0x32, 0x03, 0x50, 0x7f, 0x4e, 0x89, 0xee,
0x93, 0xc0, 0x8d, 0x2d, 0x51, 0xbb, 0x30, 0xe0, 0x23, 0x0a, 0x93, 0x43, 0x79, 0x25, 0x1d, 0xca,
0x93, 0x7b, 0x32, 0x55, 0x69, 0x4f, 0x46, 0xff, 0xa4, 0x04, 0x1d, 0xea, 0xee, 0xb6, 0x67, 0x1b,
0x03, 0x85, 0x88, 0xbe, 0x05, 0x2d, 0x7e, 0xbe, 0x2d, 0x11, 0xde, 0x7c, 0x99, 0x98, 0x0c, 0xbd,
0x0d, 0x97, 0x59, 0xa7, 0x00, 0x87, 0x53, 0x67, 0x96, 0xb6, 0xb3, 0xc4, 0x17, 0xbd, 0x64, 0x7e,
0x96, 0x34, 0x89, 0x11, 0xcf, 0xe0, 0xca, 0xd8, 0xf1, 0x07, 0xa6, 0xd3, 0x97, 0xc5, 0xc3, 0x64,
0x58, 0x40, 0xe3, 0x2f, 0xb3, 0xe1, 0x07, 0x49, 0x19, 0x86, 0x68, 0x17, 0x5a, 0x21, 0xc6, 0x2f,
0x66, 0x15, 0x41, 0xb5, 0x70, 0x45, 0xd0, 0x24, 0x03, 0xe3, 0x82, 0xe0, 0x4f, 0x35, 0x58, 0x4a,
0x6d, 0xab, 0xa6, 0xcb, 0x4f, 0x2d, 0x5b, 0x7e, 0xde, 0x83, 0x2a, 0xa9, 0xc9, 0x98, 0x33, 0x6c,
0xab, 0x4b, 0x23, 0x79, 0x56, 0x83, 0x0d, 0x40, 0x9b, 0xb0, 0xa2, 0x38, 0x4c, 0xe5, 0x3a, 0x80,
0xb2, 0x67, 0xa9, 0xfa, 0x4f, 0x2a, 0xd0, 0x48, 0xf0, 0x63, 0x4e, 0xe5, 0x5c, 0x64, 0x9f, 0x2c,
0xb5, 0xbc, 0x72, 0x76, 0x79, 0x39, 0xe7, 0x6c, 0x44, 0xef, 0x5c, 0xec, 0xb2, 0x42, 0x81, 0x57,
0x2d, 0x2e, 0x76, 0x69, 0x99, 0x90, 0xac, 0x00, 0x16, 0xa4, 0x0a, 0x20, 0x55, 0x23, 0x2d, 0x9e,
0x52, 0x23, 0xd5, 0xe4, 0x1a, 0x49, 0xb2, 0xa3, 0x7a, 0xda, 0x8e, 0x8a, 0x16, 0xb3, 0x6f, 0xc3,
0xca, 0x30, 0xc0, 0x66, 0x84, 0xad, 0x07, 0x27, 0xdb, 0x71, 0x13, 0xcf, 0xa2, 0x54, 0x4d, 0xe8,
0xe1, 0x6c, 0x7f, 0x89, 0x49, 0xb9, 0x49, 0xa5, 0xac, 0x2e, 0xc1, 0xb8, 0x6c, 0x98, 0x90, 0x85,
0x7b, 0xa6, 0x7f, 0xe9, 0x32, 0xba, 0x75, 0xae, 0x32, 0xfa, 0x26, 0x34, 0x44, 0x68, 0x25, 0xe6,
0xde, 0x66, 0x9e, 0x4f, 0xf8, 0x02, 0x2b, 0x94, 0x9c, 0xc1, 0x92, 0xbc, 0x41, 0x9b, 0x2e, 0x60,
0x3b, 0xd9, 0x02, 0xf6, 0x2a, 0x2c, 0xda, 0x61, 0x7f, 0x64, 0xbe, 0xc0, 0xdd, 0x65, 0xda, 0xba,
0x60, 0x87, 0x0f, 0xcd, 0x17, 0x58, 0xff, 0xb7, 0x32, 0xb4, 0x67, 0x15, 0x4f, 0x61, 0x37, 0x52,
0xe4, 0x42, 0xc1, 0x3e, 0x74, 0x66, 0x81, 0x9a, 0x72, 0xf8, 0xd4, 0xa2, 0x2d, 0x7d, 0xea, 0xb1,
0x34, 0x49, 0xd9, 0xab, 0xb4, 0xaf, 0x5c, 0x39, 0xd3, 0xbe, 0xf2, 0x05, 0x4f, 0x25, 0xef, 0xc2,
0x6a, 0x1c, 0x80, 0xa5, 0x65, 0xb3, 0x8a, 0xe0, 0xb2, 0x68, 0x7c, 0x92, 0x5c, 0x7e, 0x8e, 0x0b,
0x58, 0xcc, 0x73, 0x01, 0x69, 0x15, 0xa8, 0x65, 0x54, 0x20, 0x7b, 0x38, 0x5a, 0x57, 0x1c, 0x8e,
0xea, 0xcf, 0x60, 0x85, 0x6e, 0x19, 0x86, 0xc3, 0xc0, 0x1e, 0xe0, 0x38, 0x67, 0x2d, 0x22, 0xd6,
0x1e, 0xd4, 0x52, 0x69, 0x6f, 0xfc, 0xaf, 0xff, 0x8e, 0x06, 0x57, 0xb2, 0xf3, 0x52, 0x8d, 0x99,
0x39, 0x12, 0x4d, 0x72, 0x24, 0xbf, 0x0e, 0x2b, 0xb3, 0xe9, 0xe5, 0x84, 0x3a, 0x27, 0x65, 0x54,
0x10, 0x6e, 0xa0, 0xd9, 0x1c, 0x02, 0xa6, 0xff, 0x44, 0x8b, 0x77, 0x5e, 0x09, 0x6c, 0x4c, 0xf7,
0xa3, 0x49, 0x70, 0xf3, 0x3d, 0xc7, 0xf6, 0xe2, 0x0a, 0x9d, 0xaf, 0x91, 0x01, 0x79, 0x85, 0xfe,
0x2e, 0x2c, 0xf1, 0x4e, 0x71, 0x8c, 0x2a, 0x98, 0x95, 0xb5, 0xd9, 0xb8, 0x38, 0x3a, 0xdd, 0x86,
0x36, 0xdf, 0x28, 0x16, 0xf8, 0xca, 0xaa, 0xed, 0xe3, 0x5f, 0x85, 0x8e, 0xe8, 0x76, 0xd6, 0xa8,
0xb8, 0xc4, 0x07, 0xc6, 0xd9, 0xdd, 0x8f, 0x35, 0xe8, 0xca, 0x31, 0x32, 0xb1, 0xfc, 0xb3, 0xe7,
0x78, 0xdf, 0x96, 0x8f, 0xd8, 0x6e, 0x9f, 0x42, 0xcf, 0x0c, 0x8f, 0x38, 0x68, 0xdb, 0xa7, 0xc7,
0xa5, 0xa4, 0x34, 0xd9, 0xb1, 0xc3, 0x28, 0xb0, 0x07, 0xd3, 0x0b, 0x5d, 0x17, 0xd1, 0xff, 0xae,
0x04, 0x5f, 0x55, 0x4e, 0x78, 0x91, 0xc3, 0xb4, 0xbc, 0x5d, 0x83, 0x07, 0x50, 0x4b, 0x95, 0x30,
0xaf, 0x9d, 0xb2, 0x78, 0xbe, 0x01, 0xc6, 0x36, 0x62, 0xc4, 0x38, 0x32, 0x47, 0xac, 0xd3, 0x95,
0xfc, 0x39, 0xb8, 0xd2, 0x4a, 0x73, 0x88, 0x71, 0xe8, 0x3e, 0x34, 0x59, 0x79, 0xd8, 0x3f, 0xb2,
0xf1, 0xb1, 0x38, 0x03, 0xba, 0xa1, 0xf4, 0x6b, 0xb4, 0xdf, 0x73, 0x1b, 0x1f, 0x1b, 0x0d, 0x27,
0xfe, 0x0e, 0xf5, 0xff, 0x2d, 0x03, 0xcc, 0xda, 0x48, 0x6d, 0x3a, 0x33, 0x18, 0x6e, 0x01, 0x09,
0x08, 0x09, 0xc4, 0x72, 0xee, 0x27, 0x7e, 0x91, 0x31, 0xdb, 0xca, 0xb5, 0xec, 0x30, 0xe2, 0x7c,
0xd9, 0x3c, 0x9d, 0x16, 0xc1, 0x22, 0x22, 0x32, 0x76, 0xc4, 0x22, 0x6a, 0x2f, 0x02, 0x41, 0x6f,
0x01, 0x1a, 0x07, 0xfe, 0xb1, 0xed, 0x8d, 0x93, 0x19, 0x3b, 0x4b, 0xec, 0x97, 0x79, 0x4b, 0x22,
0x65, 0xff, 0x21, 0x74, 0x52, 0xdd, 0x05, 0x4b, 0xee, 0xce, 0x21, 0x63, 0x57, 0x9a, 0x8b, 0x9f,
0xf6, 0x2c, 0xc9, 0x18, 0xc2, 0x5e, 0x1f, 0x3a, 0x69, 0x7a, 0x15, 0xe7, 0x35, 0xdf, 0x90, 0xcf,
0x6b, 0x4e, 0x33, 0x53, 0x32, 0x4d, 0xe2, 0xc0, 0xa6, 0x37, 0x82, 0xcb, 0x2a, 0x4a, 0x14, 0x48,
0xee, 0xc9, 0x48, 0x8a, 0xe4, 0xb4, 0x89, 0x83, 0xa1, 0xef, 0xc5, 0xe9, 0x22, 0x65, 0x73, 0x9e,
0x07, 0x4e, 0x6c, 0xe0, 0x95, 0xa4, 0x0d, 0x3c, 0xfd, 0x8f, 0x34, 0x40, 0x59, 0xed, 0x46, 0x6d,
0x28, 0xc5, 0x93, 0x94, 0xf6, 0x76, 0x52, 0xda, 0x54, 0xca, 0x68, 0xd3, 0x35, 0xa8, 0xc7, 0x11,
0x91, 0xbb, 0xbf, 0x19, 0x20, 0xa9, 0x6b, 0x15, 0x59, 0xd7, 0x12, 0x84, 0x55, 0x65, 0xc2, 0x0e,
0x01, 0x65, 0x2d, 0x26, 0x39, 0x93, 0x26, 0xcf, 0x34, 0x8f, 0xc2, 0x04, 0xa6, 0xb2, 0x8c, 0xe9,
0x3f, 0x4b, 0x80, 0x66, 0x31, 0x3f, 0x3e, 0xb4, 0x2a, 0x12, 0x28, 0x37, 0x61, 0x25, 0x9b, 0x11,
0x88, 0x34, 0x08, 0x65, 0xf2, 0x01, 0x55, 0xec, 0x2e, 0xab, 0x2e, 0x36, 0xbd, 0x13, 0xfb, 0x38,
0x96, 0xe0, 0xdc, 0xc8, 0x4b, 0x70, 0x52, 0x6e, 0xee, 0x37, 0xd2, 0x17, 0xa2, 0x98, 0xd1, 0xdc,
0x53, 0xfa, 0xa3, 0xcc, 0x92, 0xe7, 0xdd, 0x86, 0xba, 0xf8, 0x55, 0xa6, 0x7f, 0x2f, 0xc1, 0x72,
0xcc, 0x8d, 0x33, 0x71, 0x7a, 0xfe, 0x21, 0xe1, 0x67, 0xcc, 0xda, 0x0f, 0xd5, 0xac, 0xfd, 0xe5,
0x53, 0x73, 0xd8, 0xcf, 0x8f, 0xb3, 0x1f, 0xc3, 0x22, 0xdf, 0x3e, 0xcb, 0xd8, 0x6e, 0x91, 0x2a,
0xf1, 0x32, 0x54, 0x89, 0xab, 0x10, 0xfb, 0x49, 0xec, 0x87, 0xb1, 0x34, 0x79, 0xc7, 0x8d, 0x9b,
0x6f, 0x4b, 0xba, 0xe2, 0xa6, 0xff, 0x8d, 0x06, 0x70, 0x70, 0xe2, 0x0d, 0xef, 0x33, 0x4b, 0x7b,
0x1b, 0x2a, 0xf3, 0xee, 0x7c, 0x90, 0xde, 0x34, 0x37, 0xa7, 0x3d, 0x0b, 0x08, 0x57, 0xaa, 0x83,
0xcb, 0xe9, 0x3a, 0x38, 0xaf, 0x82, 0xcd, 0xf7, 0x2e, 0xff, 0xa8, 0xc1, 0x55, 0x42, 0xc4, 0xa7,
0x92, 0xb2, 0x14, 0xe2, 0x70, 0xc2, 0x73, 0x95, 0x65, 0xcf, 0x75, 0x0f, 0x16, 0x59, 0x29, 0x2a,
0xd2, 0x87, 0x1b, 0x79, 0x2c, 0x63, 0x0c, 0x36, 0x44, 0x77, 0xfd, 0x19, 0xb4, 0x8c, 0xa4, 0x24,
0x10, 0x82, 0x4a, 0xe2, 0x66, 0x0f, 0xfd, 0xa6, 0xc9, 0xbc, 0x39, 0x31, 0x87, 0x76, 0x74, 0x42,
0x09, 0xab, 0x1a, 0xf1, 0xbf, 0x5a, 0xec, 0xfa, 0x4f, 0x35, 0xb8, 0x22, 0xce, 0x1a, 0xb8, 0x52,
0x9d, 0x9f, 0x37, 0x5b, 0xb0, 0xca, 0x35, 0x28, 0xa5, 0x4a, 0x2c, 0xeb, 0x58, 0x61, 0x30, 0x79,
0x19, 0x5b, 0xb0, 0x1a, 0x99, 0xc1, 0x18, 0x47, 0xe9, 0x31, 0x8c, 0x73, 0x2b, 0xac, 0x51, 0x1e,
0x53, 0xe4, 0xac, 0xe7, 0x26, 0x3b, 0xad, 0xe7, 0x0e, 0x81, 0xeb, 0x04, 0x78, 0x53, 0x97, 0xaf,
0x52, 0x3f, 0x86, 0x6b, 0xec, 0x6e, 0xdd, 0x40, 0xa6, 0xe8, 0x42, 0xdb, 0xa7, 0xca, 0x75, 0xa7,
0x4c, 0xe8, 0xcf, 0x34, 0xb8, 0x9e, 0x83, 0xf9, 0x22, 0x69, 0xef, 0x23, 0x25, 0xf6, 0x9c, 0x0c,
0x5f, 0xc2, 0x4b, 0xf3, 0xd3, 0x14, 0x91, 0x3f, 0xab, 0xc0, 0x72, 0xa6, 0xd3, 0x99, 0x75, 0xee,
0x4d, 0x40, 0x44, 0x08, 0xf1, 0x53, 0x0d, 0x5a, 0x34, 0x71, 0x5f, 0xdd, 0xf1, 0xa6, 0x6e, 0xfc,
0x4c, 0x83, 0xd4, 0x4d, 0xc8, 0x66, 0xbd, 0xd9, 0xe6, 0x69, 0x2c, 0xb9, 0x4a, 0xfe, 0x3d, 0xdf,
0x0c, 0x81, 0x1b, 0xfb, 0x53, 0x97, 0xed, 0xb3, 0x72, 0x29, 0x33, 0xff, 0x4b, 0x50, 0x49, 0x60,
0x34, 0x82, 0x65, 0x7a, 0x97, 0x63, 0x1a, 0x8d, 0x7d, 0x92, 0x79, 0x52, 0xba, 0x98, 0x97, 0xff,
0x56, 0x61, 0x4c, 0xef, 0xf3, 0xd1, 0x84, 0x78, 0x9e, 0x7c, 0x7a, 0x32, 0x54, 0xe0, 0xb1, 0xbd,
0xa1, 0xef, 0xc6, 0x78, 0x16, 0xce, 0x88, 0x67, 0x8f, 0x8f, 0x96, 0xf1, 0x24, 0xa1, 0xbd, 0x6d,
0x58, 0x55, 0x2e, 0x7d, 0x5e, 0x5c, 0xa9, 0x26, 0x13, 0xd9, 0x07, 0x70, 0x59, 0xb5, 0xaa, 0x73,
0xcc, 0x91, 0xa1, 0xf8, 0x2c, 0x73, 0xdc, 0xf9, 0x15, 0xa8, 0xc7, 0xa7, 0x5f, 0xa8, 0x01, 0x8b,
0xcf, 0xbc, 0xf7, 0x3c, 0xff, 0xd8, 0xeb, 0x5c, 0x42, 0x8b, 0x50, 0xbe, 0xef, 0x38, 0x1d, 0x0d,
0xb5, 0xa0, 0x7e, 0x10, 0x05, 0xd8, 0x24, 0x48, 0x3a, 0x25, 0xd4, 0x06, 0x78, 0xd7, 0x0e, 0x23,
0x3f, 0xb0, 0x87, 0xa6, 0xd3, 0x29, 0xdf, 0xf9, 0x18, 0xda, 0xf2, 0xde, 0x12, 0x6a, 0x42, 0x6d,
0xdf, 0x8f, 0xbe, 0xff, 0x91, 0x1d, 0x46, 0x9d, 0x4b, 0xa4, 0xff, 0xbe, 0x1f, 0x3d, 0x09, 0x70,
0x88, 0xbd, 0xa8, 0xa3, 0x21, 0x80, 0x85, 0xf7, 0xbd, 0x1d, 0x3b, 0x7c, 0xd1, 0x29, 0xa1, 0x15,
0xbe, 0x6d, 0x6c, 0x3a, 0x7b, 0x7c, 0xc3, 0xa6, 0x53, 0x26, 0xc3, 0xe3, 0xbf, 0x0a, 0xea, 0x40,
0x33, 0xee, 0xb2, 0xfb, 0xe4, 0x59, 0xa7, 0x8a, 0xea, 0x50, 0x65, 0x9f, 0x0b, 0x77, 0x2c, 0xe8,
0xa4, 0xcf, 0x3c, 0xc8, 0x9c, 0x6c, 0x11, 0x31, 0xa8, 0x73, 0x89, 0xac, 0x8c, 0x1f, 0x3a, 0x75,
0x34, 0xb4, 0x04, 0x8d, 0xc4, 0x11, 0x4e, 0xa7, 0x44, 0x00, 0xbb, 0xc1, 0x64, 0xc8, 0xbd, 0x11,
0x23, 0x81, 0xb0, 0x73, 0x87, 0x70, 0xa2, 0x72, 0xe7, 0x01, 0xd4, 0xc4, 0xa6, 0x17, 0xe9, 0xca,
0x59, 0x44, 0x7e, 0x3b, 0x97, 0xd0, 0x32, 0xb4, 0xa4, 0x2b, 0xf0, 0x1d, 0x0d, 0x21, 0x68, 0xcb,
0x8f, 0x54, 0x3a, 0xa5, 0x3b, 0x5b, 0x00, 0xb3, 0xe4, 0x87, 0x90, 0xb3, 0xe7, 0x1d, 0x99, 0x8e,
0x6d, 0x31, 0xda, 0x48, 0x13, 0xe1, 0x2e, 0xe5, 0x0e, 0xd3, 0xac, 0x4e, 0xe9, 0xce, 0x4d, 0xa8,
0x89, 0x80, 0x4e, 0xe0, 0x06, 0x76, 0xfd, 0x23, 0xcc, 0x24, 0x73, 0x80, 0xa3, 0x8e, 0xb6, 0xf5,
0x53, 0x04, 0xc0, 0x8e, 0x29, 0x7c, 0x3f, 0xb0, 0x90, 0x03, 0x68, 0x17, 0x47, 0xdb, 0xbe, 0x3b,
0xf1, 0x3d, 0xb1, 0x7d, 0x1a, 0xa2, 0x0d, 0x59, 0xf7, 0xf9, 0x4f, 0xb6, 0x23, 0x5f, 0x7d, 0xef,
0x55, 0x65, 0xff, 0x54, 0x67, 0xfd, 0x12, 0x72, 0x29, 0xb6, 0xa7, 0xb6, 0x8b, 0x9f, 0xda, 0xc3,
0x17, 0xf1, 0xd9, 0x46, 0xfe, 0xf3, 0x90, 0x54, 0x57, 0x81, 0xef, 0x96, 0x12, 0xdf, 0x41, 0x14,
0xd8, 0xde, 0x58, 0x78, 0x69, 0xfd, 0x12, 0x7a, 0x99, 0x7a, 0x9c, 0x22, 0x10, 0x6e, 0x15, 0x79,
0x8f, 0x72, 0x3e, 0x94, 0x0e, 0x2c, 0xa5, 0xde, 0xeb, 0xa1, 0x3b, 0xea, 0xcb, 0xc2, 0xaa, 0xb7,
0x85, 0xbd, 0x37, 0x0a, 0xf5, 0x8d, 0xb1, 0xd9, 0xd0, 0x96, 0xdf, 0xa4, 0xa1, 0x5f, 0xca, 0x9b,
0x20, 0xf3, 0x5c, 0xa1, 0x77, 0xa7, 0x48, 0xd7, 0x18, 0xd5, 0x07, 0x4c, 0x41, 0xe7, 0xa1, 0x52,
0x3e, 0xed, 0xe8, 0x9d, 0x16, 0x20, 0xf5, 0x4b, 0xe8, 0x47, 0x24, 0x96, 0xa5, 0x1e, 0x55, 0xa0,
0x37, 0xd5, 0xfe, 0x57, 0xfd, 0xf6, 0x62, 0x1e, 0x86, 0x0f, 0xd2, 0xe6, 0x95, 0x4f, 0x7d, 0xe6,
0x99, 0x55, 0x71, 0xea, 0x13, 0xd3, 0x9f, 0x46, 0xfd, 0x99, 0x31, 0x4c, 0xa9, 0xd9, 0xa4, 0x0f,
0xcb, 0xde, 0x52, 0xa1, 0xc8, 0x7d, 0xd9, 0xd1, 0xdb, 0x28, 0xda, 0x3d, 0xa9, 0x5d, 0xf2, 0xe3,
0x01, 0x35, 0xd3, 0x94, 0x0f, 0x1e, 0xd4, 0xda, 0xa5, 0x7e, 0x8b, 0xa0, 0x5f, 0x42, 0x4f, 0x25,
0xf7, 0x8a, 0x5e, 0xcb, 0x13, 0x8e, 0x7c, 0x84, 0x3e, 0x8f, 0x6f, 0xbf, 0x09, 0x88, 0xd9, 0x8e,
0x37, 0xb2, 0xc7, 0xd3, 0xc0, 0x64, 0x8a, 0x95, 0xe7, 0x6e, 0xb2, 0x5d, 0x05, 0x9a, 0xaf, 0x9d,
0x61, 0x44, 0xbc, 0xa4, 0x3e, 0xc0, 0x2e, 0x8e, 0x1e, 0xe3, 0x28, 0xb0, 0x87, 0x61, 0x7a, 0x45,
0x33, 0x8f, 0xca, 0x3b, 0x08, 0x54, 0xaf, 0xcf, 0xed, 0x17, 0x23, 0x18, 0x40, 0x63, 0x97, 0x64,
0xde, 0x34, 0x9b, 0x08, 0x51, 0xee, 0x48, 0xd1, 0x43, 0xa0, 0x58, 0x9f, 0xdf, 0x31, 0xe9, 0xce,
0x52, 0x0f, 0x29, 0x50, 0xae, 0x60, 0xb3, 0xcf, 0x3b, 0xd4, 0xee, 0x2c, 0xe7, 0x65, 0x06, 0x5b,
0xd1, 0xf6, 0x21, 0x1e, 0xbe, 0x78, 0x17, 0x9b, 0x4e, 0x74, 0x98, 0xb3, 0xa2, 0x44, 0x8f, 0xd3,
0x57, 0x24, 0x75, 0x8c, 0x71, 0x60, 0x58, 0xd9, 0xa6, 0x27, 0x8f, 0x72, 0xc9, 0xb2, 0xa9, 0x9e,
0x22, 0xdb, 0xb3, 0xa0, 0xea, 0x99, 0xb0, 0xbc, 0x13, 0xf8, 0x13, 0x19, 0xc9, 0x5b, 0x4a, 0x24,
0x99, 0x7e, 0x05, 0x51, 0xfc, 0x00, 0x9a, 0xa2, 0x32, 0xa4, 0xb9, 0xac, 0x9a, 0x0b, 0xc9, 0x2e,
0x05, 0x27, 0xfe, 0x10, 0x96, 0x52, 0x25, 0xa7, 0x5a, 0xe8, 0xea, 0xba, 0x74, 0xde, 0xec, 0xc7,
0x80, 0xe8, 0xeb, 0x18, 0xe9, 0x65, 0x5e, 0x4e, 0xc6, 0x91, 0xed, 0x28, 0x90, 0x6c, 0x16, 0xee,
0x1f, 0x4b, 0xfe, 0xb7, 0x60, 0x55, 0x59, 0xd6, 0xa5, 0x1d, 0x02, 0xbf, 0xdf, 0x75, 0x4a, 0xed,
0x99, 0x76, 0x08, 0xa7, 0x8e, 0x10, 0xf8, 0xb7, 0x3e, 0x69, 0x43, 0x9d, 0x66, 0x5e, 0x54, 0x5a,
0xbf, 0x48, 0xbc, 0x3e, 0xdd, 0xc4, 0xeb, 0x43, 0x58, 0x4a, 0xbd, 0x38, 0x51, 0x2b, 0xad, 0xfa,
0x59, 0x4a, 0x81, 0xfc, 0x41, 0x7e, 0xf3, 0xa1, 0x0e, 0x85, 0xca, 0x77, 0x21, 0xf3, 0xe6, 0x7e,
0xce, 0x1e, 0x6b, 0xc5, 0x67, 0x98, 0xaf, 0xe7, 0xee, 0x82, 0xca, 0x77, 0xdf, 0xbe, 0xf8, 0xbc,
0xe4, 0xb3, 0xcf, 0xdb, 0x3e, 0x84, 0xa5, 0xd4, 0x6d, 0x65, 0xb5, 0x54, 0xd5, 0x57, 0x9a, 0xe7,
0xcd, 0xfe, 0x39, 0x26, 0x38, 0x16, 0xac, 0x28, 0x2e, 0x87, 0xa2, 0x8d, 0xbc, 0xed, 0x45, 0xf5,
0x2d, 0xd2, 0xf9, 0x0b, 0x6a, 0x49, 0xa6, 0x94, 0x8e, 0x09, 0x33, 0x22, 0xd3, 0xcf, 0xee, 0x7b,
0x6f, 0x16, 0x7b, 0xa3, 0x1f, 0x2f, 0xe8, 0x00, 0x16, 0xd8, 0x1d, 0x66, 0xf4, 0x8a, 0xfa, 0x2c,
0x2e, 0x71, 0xbf, 0xb9, 0x37, 0xef, 0x16, 0x74, 0x38, 0x75, 0xa2, 0x90, 0x4e, 0x5a, 0xa5, 0x1e,
0x12, 0x29, 0x2f, 0xdf, 0x27, 0x2f, 0x13, 0xf7, 0xe6, 0xdf, 0x1f, 0x16, 0x93, 0xfe, 0xff, 0xce,
0x02, 0x3f, 0x82, 0x15, 0xc5, 0x09, 0x3d, 0xca, 0xcb, 0xf6, 0x73, 0xee, 0x06, 0xf4, 0x36, 0x0b,
0xf7, 0x8f, 0x31, 0xff, 0x10, 0x3a, 0xe9, 0x6d, 0x7b, 0xf4, 0x46, 0x9e, 0x3e, 0xab, 0x70, 0x9e,
0xae, 0xcc, 0x0f, 0xbe, 0xfe, 0xc1, 0xd6, 0xd8, 0x8e, 0x0e, 0xa7, 0x03, 0xd2, 0xb2, 0xc9, 0xba,
0xbe, 0x65, 0xfb, 0xfc, 0x6b, 0x53, 0xf0, 0x7f, 0x93, 0x8e, 0xde, 0xa4, 0xa8, 0x26, 0x83, 0xc1,
0x02, 0xfd, 0xbd, 0xfb, 0x7f, 0x01, 0x00, 0x00, 0xff, 0xff, 0x96, 0x39, 0x0f, 0x0f, 0x34, 0x48,
0x00, 0x00,
}
// Reference imports to suppress errors if they are not otherwise used.

View File

@ -18,7 +18,7 @@ import (
// type pickShardPolicy func(ctx context.Context, mgr *shardClientMgr, query func(UniqueID, types.QueryNode) error, leaders []nodeInfo) error
type pickShardPolicy func(context.Context, *shardClientMgr, func(context.Context, UniqueID, types.QueryNode, []string) error, map[string][]nodeInfo) error
type pickShardPolicy func(context.Context, *shardClientMgr, func(context.Context, UniqueID, types.QueryNode, []string, int) error, map[string][]nodeInfo) error
var (
errBegin = errors.New("begin error")
@ -106,10 +106,11 @@ func groupShardleadersWithSameQueryNode(
func mergeRoundRobinPolicy(
ctx context.Context,
mgr *shardClientMgr,
query func(context.Context, UniqueID, types.QueryNode, []string) error,
query func(context.Context, UniqueID, types.QueryNode, []string, int) error,
dml2leaders map[string][]nodeInfo) error {
nexts := make(map[string]int)
errSet := make(map[string]error) // record err for dml channels
totalChannelNum := len(dml2leaders)
for dml := range dml2leaders {
nexts[dml] = 0
}
@ -128,7 +129,7 @@ func mergeRoundRobinPolicy(
qn := nodeset[nodeID]
go func() {
defer wg.Done()
if err := query(ctx, nodeID, qn, channels); err != nil {
if err := query(ctx, nodeID, qn, channels, totalChannelNum); err != nil {
log.Ctx(ctx).Warn("failed to do query with node", zap.Int64("nodeID", nodeID),
zap.Strings("dmlChannels", channels), zap.Error(err))
mu.Lock()

View File

@ -169,7 +169,7 @@ type mockQuery struct {
failset map[UniqueID]error
}
func (m *mockQuery) query(_ context.Context, nodeID UniqueID, qn types.QueryNode, chs []string) error {
func (m *mockQuery) query(_ context.Context, nodeID UniqueID, qn types.QueryNode, chs []string, _ int) error {
m.mu.Lock()
defer m.mu.Unlock()
if err, ok := m.failset[nodeID]; ok {

View File

@ -429,7 +429,7 @@ func (t *queryTask) PostExecute(ctx context.Context) error {
return nil
}
func (t *queryTask) queryShard(ctx context.Context, nodeID int64, qn types.QueryNode, channelIDs []string) error {
func (t *queryTask) queryShard(ctx context.Context, nodeID int64, qn types.QueryNode, channelIDs []string, _ int) error {
retrieveReq := typeutil.Clone(t.RetrieveRequest)
retrieveReq.GetBase().TargetID = nodeID
req := &querypb.QueryRequest{

View File

@ -43,7 +43,7 @@ func TestQueryTask_all(t *testing.T) {
expr = fmt.Sprintf("%s > 0", testInt64Field)
hitNum = 10
errPolicy = func(context.Context, *shardClientMgr, func(context.Context, int64, types.QueryNode, []string) error, map[string][]nodeInfo) error {
errPolicy = func(context.Context, *shardClientMgr, func(context.Context, int64, types.QueryNode, []string, int) error, map[string][]nodeInfo) error {
return fmt.Errorf("fake error")
}
)

View File

@ -2,7 +2,6 @@ package proxy
import (
"context"
"encoding/json"
"errors"
"fmt"
"regexp"
@ -94,61 +93,6 @@ func getPartitionIDs(ctx context.Context, collectionName string, partitionNames
return partitionIDs, nil
}
func parseSearchParams(searchParamsPair []*commonpb.KeyValuePair) (string, error) {
searchParamStr, err := funcutil.GetAttrByKeyFromRepeatedKV(SearchParamsKey, searchParamsPair)
if Params.AutoIndexConfig.Enable {
searchParamMap := make(map[string]interface{})
var level int
if err == nil { // if specified params, we try to parse params
err = json.Unmarshal([]byte(searchParamStr), &searchParamMap)
if err == nil { // if unmarshal success, we try to parse level
if searchParamMap == nil { // is searchParamStr equal "null", searchParamMap will become nil!
searchParamMap = make(map[string]interface{})
}
levelValue, ok := searchParamMap[SearchLevelKey]
if !ok { // if level is not specified, set to default 1
level = 1
} else {
switch lValue := levelValue.(type) {
case float64: // for numeric values, json unmarshal will interpret it as float64
level = int(lValue)
case string:
level, err = strconv.Atoi(lValue)
default:
err = fmt.Errorf("wrong level in search params")
}
}
}
if err != nil {
return "", fmt.Errorf("search params in wrong format:%w", err)
}
} else {
level = 1
}
calculator := Params.AutoIndexConfig.GetSearchParamStrCalculator(level)
if calculator == nil {
return "", fmt.Errorf("search params calculator not found for level:%d", level)
}
newSearchParamMap, err2 := calculator.Calculate(searchParamsPair)
if err2 != nil {
return "", errors.New("search params calculate failed")
}
for k, v := range newSearchParamMap {
searchParamMap[k] = v
}
searchParamValue, err2 := json.Marshal(searchParamMap)
if err2 != nil {
return "", err2
}
searchParamStr = string(searchParamValue)
} else {
if err != nil {
return "", errors.New(SearchParamsKey + " not found in search_params")
}
}
return searchParamStr, nil
}
// parseSearchInfo returns QueryInfo and offset
func parseSearchInfo(searchParamsPair []*commonpb.KeyValuePair) (*planpb.QueryInfo, int64, error) {
topKStr, err := funcutil.GetAttrByKeyFromRepeatedKV(TopKKey, searchParamsPair)
@ -201,7 +145,7 @@ func parseSearchInfo(searchParamsPair []*commonpb.KeyValuePair) (*planpb.QueryIn
if roundDecimal != -1 && (roundDecimal > 6 || roundDecimal < 0) {
return nil, 0, fmt.Errorf("%s [%s] is invalid, should be -1 or an integer in range [0, 6]", RoundDecimalKey, roundDecimalStr)
}
searchParamStr, err := parseSearchParams(searchParamsPair)
searchParamStr, err := funcutil.GetAttrByKeyFromRepeatedKV(SearchParamsKey, searchParamsPair)
if err != nil {
return nil, 0, err
}
@ -493,13 +437,14 @@ func (t *searchTask) PostExecute(ctx context.Context) error {
return nil
}
func (t *searchTask) searchShard(ctx context.Context, nodeID int64, qn types.QueryNode, channelIDs []string) error {
func (t *searchTask) searchShard(ctx context.Context, nodeID int64, qn types.QueryNode, channelIDs []string, channelNum int) error {
searchReq := typeutil.Clone(t.SearchRequest)
searchReq.GetBase().TargetID = nodeID
req := &querypb.SearchRequest{
Req: searchReq,
DmlChannels: channelIDs,
Scope: querypb.DataScope_All,
Req: searchReq,
DmlChannels: channelIDs,
Scope: querypb.DataScope_All,
TotalChannelNum: int32(channelNum),
}
queryNode := querynode.GetQueryNode()

View File

@ -2,7 +2,6 @@ package proxy
import (
"context"
"encoding/json"
"errors"
"fmt"
"math"
@ -12,8 +11,6 @@ import (
"time"
"github.com/golang/protobuf/proto"
"github.com/milvus-io/milvus/internal/util/autoindex"
"github.com/milvus-io/milvus/internal/util/indexparamcheck"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
@ -1754,7 +1751,7 @@ func TestSearchTask_ErrExecute(t *testing.T) {
shardsNum = int32(2)
collectionName = t.Name() + funcutil.GenRandomStr()
errPolicy = func(context.Context, *shardClientMgr, func(context.Context, int64, types.QueryNode, []string) error, map[string][]nodeInfo) error {
errPolicy = func(context.Context, *shardClientMgr, func(context.Context, int64, types.QueryNode, []string, int) error, map[string][]nodeInfo) error {
return fmt.Errorf("fake error")
}
)
@ -2011,203 +2008,6 @@ func TestTaskSearch_parseQueryInfo(t *testing.T) {
})
}
func TestTaskSearch_parseSearchParams_AutoIndexEnable(t *testing.T) {
oldEnable := Params.AutoIndexConfig.Enable
oldIndexType := Params.AutoIndexConfig.IndexType
oldIndexParams := Params.AutoIndexConfig.IndexParams
oldSearchParamYamStr := Params.AutoIndexConfig.SearchParamsYamlStr
oldParser := Params.AutoIndexConfig.Parser
//parseSearchParams
Params.AutoIndexConfig.Enable = true
Params.AutoIndexConfig.IndexType = indexparamcheck.IndexHNSW
Params.AutoIndexConfig.IndexParams = make(map[string]string)
buildParams := map[string]interface{}{
common.MetricTypeKey: indexparamcheck.L2,
common.IndexTypeKey: indexparamcheck.IndexHNSW,
"M": 8,
"efConstruction": 50,
}
buildParamsJSONValue, err := json.Marshal(buildParams)
assert.NoError(t, err)
Params.AutoIndexConfig.IndexParams, err = funcutil.ParseIndexParamsMap(string(buildParamsJSONValue))
assert.NoError(t, err)
jsonStr := `
{
"1": {
"bp": [10, 90],
"functions": [
"__ef = __topk * 2.2 + 31",
"__ef = __topk * 1.58 + 39",
"__ef = __topk"
]
},
"2": {
"bp": [10, 200],
"functions": [
"__ef = __topk *3 + 64",
"__ef = 8 * pow(__topk, 0.7) + 50",
"__ef = __topk"
]
},
"3": {
"bp": [10, 300],
"functions": [
"__ef = 10 * pow(__topk, 0.7) + 80",
"__ef = 10 * pow(__topk, 0.66) + 74",
"__ef = __topk"
]
}
}`
Params.AutoIndexConfig.Parser = autoindex.NewParser()
Params.AutoIndexConfig.Parser.InitFromJSONStr(jsonStr)
normalKVPairs := []*commonpb.KeyValuePair{
{
Key: AnnsFieldKey,
Value: testFloatVecField,
},
{
Key: TopKKey,
Value: "10",
},
{
Key: RoundDecimalKey,
Value: "-1",
},
{
Key: common.MetricTypeKey,
Value: indexparamcheck.L2,
},
}
normalWithNilParams := append(normalKVPairs,
&commonpb.KeyValuePair{
Key: SearchParamsKey,
Value: "null",
},
)
//var normalWithLevel []*commonpb.KeyValuePair
normalWithEmptyParams := append(normalKVPairs,
&commonpb.KeyValuePair{
Key: SearchParamsKey,
Value: "{}",
},
)
normalWithNormalLevel := append(normalKVPairs,
&commonpb.KeyValuePair{
Key: SearchParamsKey,
Value: `{"level": 1 }`,
},
)
normalWithNormalStrLevel := append(normalKVPairs,
&commonpb.KeyValuePair{
Key: SearchParamsKey,
Value: `{"level": "1" }`,
},
)
normalTests := []struct {
description string
params []*commonpb.KeyValuePair
}{
{"normal", normalKVPairs},
{"normal_with_nil_params", normalWithNilParams},
{"normal_with_empty_params", normalWithEmptyParams},
{"normal_with_normal_level", normalWithNormalLevel},
{"normal_with_normal_str_level", normalWithNormalStrLevel},
}
for _, test := range normalTests {
t.Run(test.description, func(t *testing.T) {
_, _, err := parseSearchInfo(test.params)
assert.NoError(t, err)
})
}
invalidWithWrongParams := append(normalKVPairs,
&commonpb.KeyValuePair{
Key: SearchParamsKey,
Value: "",
},
)
invalidWithWrongLevel := append(normalKVPairs,
&commonpb.KeyValuePair{
Key: SearchParamsKey,
Value: `{"level":x}`,
},
)
invalidWithWrongStrLevel := append(normalKVPairs,
&commonpb.KeyValuePair{
Key: SearchParamsKey,
Value: `{"level":"x"}`,
},
)
invalidWithSmallLevel := append(normalKVPairs,
&commonpb.KeyValuePair{
Key: SearchParamsKey,
Value: `{"level":-1}`,
},
)
invalidWithSmallStrLevel := append(normalKVPairs,
&commonpb.KeyValuePair{
Key: SearchParamsKey,
Value: `{"level":"-1"}`,
},
)
invalidWithLargeLevel := append(normalKVPairs,
&commonpb.KeyValuePair{
Key: SearchParamsKey,
Value: `{"level":100}`,
},
)
invalidWithLargeStrLevel := append(normalKVPairs,
&commonpb.KeyValuePair{
Key: SearchParamsKey,
Value: `{"level":"100"}`,
},
)
invalidTests := []struct {
description string
params []*commonpb.KeyValuePair
}{
{"invalid_wrong_params", invalidWithWrongParams},
{"invalid_wrong_level", invalidWithWrongLevel},
{"invalid_wrong_str_level", invalidWithWrongStrLevel},
{"invalid_with_small_level", invalidWithSmallLevel},
{"invalid_with_small_str_level", invalidWithSmallStrLevel},
{"invalid_with_large_level", invalidWithLargeLevel},
{"invalid_with_large_str_level", invalidWithLargeStrLevel},
}
for _, test := range invalidTests {
t.Run(test.description, func(t *testing.T) {
info, offset, err := parseSearchInfo(test.params)
assert.Error(t, err)
assert.Nil(t, info)
assert.Zero(t, offset)
})
}
Params.AutoIndexConfig.Enable = oldEnable
Params.AutoIndexConfig.IndexType = oldIndexType
Params.AutoIndexConfig.IndexParams = oldIndexParams
Params.AutoIndexConfig.SearchParamsYamlStr = oldSearchParamYamStr
Params.AutoIndexConfig.Parser = oldParser
}
func getSearchResultData(nq, topk int64) *schemapb.SearchResultData {
result := schemapb.SearchResultData{
NumQueries: nq,

View File

@ -287,7 +287,7 @@ func (g *getStatisticsTask) getStatisticsFromQueryNode(ctx context.Context) erro
return nil
}
func (g *getStatisticsTask) getStatisticsShard(ctx context.Context, nodeID int64, qn types.QueryNode, channelIDs []string) error {
func (g *getStatisticsTask) getStatisticsShard(ctx context.Context, nodeID int64, qn types.QueryNode, channelIDs []string, _ int) error {
req := &querypb.GetStatisticsRequest{
Req: g.GetStatisticsRequest,
DmlChannels: channelIDs,

View File

@ -154,14 +154,14 @@ func TestStatisticTask_all(t *testing.T) {
assert.Greater(t, task.TimeoutTimestamp, typeutil.ZeroTimestamp)
task.ctx = ctx
task.statisticShardPolicy = func(context.Context, *shardClientMgr, func(context.Context, int64, types.QueryNode, []string) error, map[string][]nodeInfo) error {
task.statisticShardPolicy = func(context.Context, *shardClientMgr, func(context.Context, int64, types.QueryNode, []string, int) error, map[string][]nodeInfo) error {
return fmt.Errorf("fake error")
}
task.fromQueryNode = true
assert.Error(t, task.Execute(ctx))
assert.NoError(t, task.PostExecute(ctx))
task.statisticShardPolicy = func(context.Context, *shardClientMgr, func(context.Context, int64, types.QueryNode, []string) error, map[string][]nodeInfo) error {
task.statisticShardPolicy = func(context.Context, *shardClientMgr, func(context.Context, int64, types.QueryNode, []string, int) error, map[string][]nodeInfo) error {
return errInvalidShardLeaders
}
task.fromQueryNode = true

View File

@ -40,6 +40,7 @@ import (
"github.com/milvus-io/milvus/internal/metrics"
"github.com/milvus-io/milvus/internal/proto/datapb"
"github.com/milvus-io/milvus/internal/proto/internalpb"
"github.com/milvus-io/milvus/internal/proto/planpb"
"github.com/milvus-io/milvus/internal/proto/querypb"
"github.com/milvus-io/milvus/internal/util/metricsinfo"
"github.com/milvus-io/milvus/internal/util/timerecord"
@ -751,11 +752,12 @@ func (node *QueryNode) Search(ctx context.Context, req *querypb.SearchRequest) (
for _, ch := range req.GetDmlChannels() {
ch := ch
req := &querypb.SearchRequest{
Req: req.Req,
Req: typeutil.Clone(req.Req),
DmlChannels: []string{ch},
SegmentIDs: req.SegmentIDs,
FromShardLeader: req.FromShardLeader,
Scope: req.Scope,
TotalChannelNum: req.TotalChannelNum,
}
runningGp.Go(func() error {
ret, err := node.searchWithDmlChannel(runningCtx, req, ch)
@ -899,6 +901,45 @@ func (node *QueryNode) searchWithDmlChannel(ctx context.Context, req *querypb.Se
)
defer cancel()
// optimize search params
if req.Req.GetSerializedExprPlan() != nil && node.queryHook != nil {
channelNum := int(req.GetTotalChannelNum())
if channelNum <= 0 {
channelNum = 1
}
estSegmentNum := len(cluster.GetSegmentInfos()) * channelNum
log.Debug("estimate segment num:", zap.Int("estSegmentNum", estSegmentNum), zap.Int("channleNum", channelNum))
plan := &planpb.PlanNode{}
err = proto.Unmarshal(req.Req.GetSerializedExprPlan(), plan)
if err != nil {
failRet.Status.Reason = err.Error()
return failRet, nil
}
switch plan.GetNode().(type) {
case *planpb.PlanNode_VectorAnns:
qinfo := plan.GetVectorAnns().GetQueryInfo()
paramMap := map[string]interface{}{
common.TopKKey: qinfo.GetTopk(),
common.SearchParamKey: qinfo.GetSearchParams(),
common.SegmentNumKey: estSegmentNum,
}
err := node.queryHook.Run(paramMap)
if err != nil {
failRet.Status.Reason = err.Error()
return failRet, nil
}
qinfo.Topk = paramMap[common.TopKKey].(int64)
qinfo.SearchParams = paramMap[common.SearchParamKey].(string)
SerializedExprPlan, err := proto.Marshal(plan)
if err != nil {
failRet.Status.Reason = err.Error()
return failRet, nil
}
req.Req.SerializedExprPlan = SerializedExprPlan
}
}
// shard leader dispatches request to its shard cluster
var withStreamingFunc searchWithStreaming
if !req.Req.IgnoreGrowing {

View File

@ -19,17 +19,20 @@ package querynode
import (
"context"
"encoding/json"
"fmt"
"math/rand"
"runtime"
"sync"
"sync/atomic"
"testing"
"github.com/golang/protobuf/proto"
"github.com/milvus-io/milvus-proto/go-api/commonpb"
"github.com/milvus-io/milvus-proto/go-api/milvuspb"
"github.com/milvus-io/milvus/internal/common"
"github.com/milvus-io/milvus/internal/proto/datapb"
"github.com/milvus-io/milvus/internal/proto/internalpb"
"github.com/milvus-io/milvus/internal/proto/planpb"
"github.com/milvus-io/milvus/internal/proto/querypb"
queryPb "github.com/milvus-io/milvus/internal/proto/querypb"
"github.com/milvus-io/milvus/internal/util/commonpbutil"
@ -37,6 +40,7 @@ import (
"github.com/milvus-io/milvus/internal/util/etcd"
"github.com/milvus-io/milvus/internal/util/metricsinfo"
"github.com/milvus-io/milvus/internal/util/sessionutil"
"github.com/milvus-io/milvus/internal/util/typeutil"
"github.com/panjf2000/ants/v2"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/mock"
@ -797,6 +801,62 @@ func TestImpl_searchWithDmlChannel(t *testing.T) {
DmlChannels: []string{defaultDMLChannel},
}, defaultDMLChannel)
assert.NoError(t, err)
// test querynode plugin
node.queryHook = &mockHook1{}
newReq := typeutil.Clone(req)
_, err = node.searchWithDmlChannel(ctx, &queryPb.SearchRequest{
Req: newReq,
FromShardLeader: false,
DmlChannels: []string{defaultDMLChannel},
TotalChannelNum: 1,
}, defaultDMLChannel)
assert.NoError(t, err)
assert.Equal(t, req.SerializedExprPlan, newReq.SerializedExprPlan)
node.queryHook = &mockHook2{}
newReq = typeutil.Clone(req)
_, err = node.searchWithDmlChannel(ctx, &queryPb.SearchRequest{
Req: newReq,
FromShardLeader: false,
DmlChannels: []string{defaultDMLChannel},
TotalChannelNum: 1,
}, defaultDMLChannel)
assert.NoError(t, err)
assert.NotEqual(t, req.SerializedExprPlan, newReq.SerializedExprPlan)
reqSearchParams, err := getSearchParamFromPlanExpr(req.SerializedExprPlan)
assert.NoError(t, err)
newReqSearchParams, err := getSearchParamFromPlanExpr(newReq.SerializedExprPlan)
assert.NoError(t, err)
assert.NotEqual(t, reqSearchParams, newReqSearchParams)
assert.Equal(t, newReqSearchParams, "test")
node.queryHook = &mockHook3{}
newReq = typeutil.Clone(req)
res, err := node.searchWithDmlChannel(ctx, &queryPb.SearchRequest{
Req: newReq,
FromShardLeader: false,
DmlChannels: []string{defaultDMLChannel},
TotalChannelNum: 1,
}, defaultDMLChannel)
assert.NoError(t, err)
assert.Equal(t, res.Status.Reason, fmt.Errorf("unexpected param").Error())
node.queryHook = &mockHook3{}
newReq = typeutil.Clone(req)
newReq.SerializedExprPlan, _ = json.Marshal("")
res, err = node.searchWithDmlChannel(ctx, &queryPb.SearchRequest{
Req: newReq,
FromShardLeader: false,
DmlChannels: []string{defaultDMLChannel},
TotalChannelNum: 1,
}, defaultDMLChannel)
assert.NoError(t, err)
plan := &planpb.PlanNode{}
err = proto.Unmarshal(newReq.SerializedExprPlan, plan)
assert.Equal(t, res.Status.Reason, err.Error())
node.queryHook = nil
// search with ignore growing segment
req.IgnoreGrowing = true
_, err = node.searchWithDmlChannel(ctx, &queryPb.SearchRequest{

View File

@ -1495,6 +1495,75 @@ func genSearchPlanAndRequests(collection *Collection, indexType string, nq int64
return newSearchRequest(collection, queryReq, queryReq.Req.GetPlaceholderGroup())
}
type mockHook1 struct {
mockString string
}
func (m *mockHook1) Init(s string) error {
if s == "test" {
return fmt.Errorf("unexpected param")
}
m.mockString = s
return nil
}
func (m *mockHook1) Run(param map[string]interface{}) error {
return nil
}
type mockHook2 struct {
}
func (m *mockHook2) Init(s string) error {
return nil
}
func (m *mockHook2) Run(param map[string]interface{}) error {
param["search_param"] = "test"
return nil
}
type mockHook3 struct {
}
func (m *mockHook3) Init(s string) error {
return nil
}
func (m *mockHook3) Run(param map[string]interface{}) error {
return fmt.Errorf("unexpected param")
}
type mockWrongHook struct{}
func getSearchParamFromPlanExpr(serializedPlan []byte) (string, error) {
plan := &planpb.PlanNode{}
err := proto.Unmarshal(serializedPlan, plan)
if err != nil {
return "", err
}
switch plan.GetNode().(type) {
case *planpb.PlanNode_VectorAnns:
qinfo := plan.GetVectorAnns().GetQueryInfo()
return qinfo.GetSearchParams(), nil
}
return "", nil
}
func genSimpleSearchPlanExpr(schema *schemapb.CollectionSchema) ([]byte, error) {
planNode := &planpb.PlanNode{
Node: &planpb.PlanNode_VectorAnns{
VectorAnns: &planpb.VectorANNS{
QueryInfo: &planpb.QueryInfo{
SearchParams: `{"nprobe":10}`,
},
},
},
}
planExpr, err := proto.Marshal(planNode)
return planExpr, err
}
func genSimpleRetrievePlanExpr(schema *schemapb.CollectionSchema) ([]byte, error) {
pkField, err := typeutil.GetPrimaryFieldSchema(schema)
if err != nil {
@ -1565,6 +1634,10 @@ func genGetPartitionStatisticRequest() (*internalpb.GetStatisticsRequest, error)
}
func genSearchRequest(nq int64, indexType string, schema *schemapb.CollectionSchema) (*internalpb.SearchRequest, error) {
expr, err := genSimpleSearchPlanExpr(schema)
if err != nil {
return nil, err
}
placeHolder, err := genPlaceHolderGroup(nq)
if err != nil {
return nil, err
@ -1574,13 +1647,14 @@ func genSearchRequest(nq int64, indexType string, schema *schemapb.CollectionSch
return nil, err2
}
return &internalpb.SearchRequest{
Base: genCommonMsgBase(commonpb.MsgType_Search, 0),
CollectionID: defaultCollectionID,
PartitionIDs: []UniqueID{defaultPartitionID},
Dsl: simpleDSL,
PlaceholderGroup: placeHolder,
DslType: commonpb.DslType_Dsl,
Nq: nq,
Base: genCommonMsgBase(commonpb.MsgType_Search, 0),
CollectionID: defaultCollectionID,
PartitionIDs: []UniqueID{defaultPartitionID},
Dsl: simpleDSL,
PlaceholderGroup: placeHolder,
DslType: commonpb.DslType_Dsl,
Nq: nq,
SerializedExprPlan: expr,
}, nil
}

View File

@ -33,6 +33,7 @@ import (
"github.com/milvus-io/milvus/internal/metrics"
"os"
"path"
"plugin"
"runtime"
"runtime/debug"
"strconv"
@ -126,6 +127,40 @@ type QueryNode struct {
taskPool *concurrency.Pool
IsStandAlone bool
queryHook Hook
}
type Hook interface {
Run(map[string]interface{}) error
Init(string) error
}
func initHook() (Hook, error) {
path := Params.QueryNodeCfg.SoPath
if path == "" {
return nil, fmt.Errorf("fail to set the querynode plugin path")
}
log.Debug("start to load plugin", zap.String("path", path))
p, err := plugin.Open(path)
if err != nil {
return nil, fmt.Errorf("fail to open the plugin, error: %s", err.Error())
}
log.Debug("plugin open")
h, err := p.Lookup("QueryNodePlugin")
if err != nil {
return nil, fmt.Errorf("fail to find the 'QueryNodePlugin' object in the plugin, error: %s", err.Error())
}
hoo, ok := h.(Hook)
if !ok {
return nil, fmt.Errorf("fail to convert the `Hook` interface")
}
if err = hoo.Init(Params.AutoIndexConfig.SearchParamsYamlStr); err != nil {
return nil, fmt.Errorf("fail to init configs for the hook, error: %s", err.Error())
}
return hoo, nil
}
var queryNode *QueryNode = nil
@ -145,6 +180,16 @@ func NewQueryNode(ctx context.Context, factory dependency.Factory) *QueryNode {
IsStandAlone: os.Getenv(metricsinfo.DeployModeEnvKey) == metricsinfo.StandaloneDeployMode,
}
// init queryhook
var err error
queryNode.queryHook, err = initHook()
if err != nil {
log.Error("load queryhook failed", zap.Error(err))
if Params.AutoIndexConfig.Enable {
panic(err)
}
}
queryNode.tSafeReplica = newTSafeReplica()
queryNode.scheduler = newTaskScheduler(ctx1, queryNode.tSafeReplica)
queryNode.UpdateStateCode(commonpb.StateCode_Abnormal)

View File

@ -48,6 +48,29 @@ func setup() {
Params.EtcdCfg.MetaRootPath = "/etcd/test/root/querynode"
}
func TestInitHook(t *testing.T) {
Params.QueryNodeCfg.SoPath = ""
a, err := initHook()
assert.Nil(t, a)
assert.NotNil(t, err)
Params.QueryNodeCfg.SoPath = "/a/b/hook.so"
a, err = initHook()
assert.Nil(t, a)
assert.NotNil(t, err)
Params.QueryNodeCfg.SoPath = ""
a = &mockHook1{}
assert.Equal(t, a.(*mockHook1).mockString, "")
assert.Error(t, a.Init("test"))
assert.NoError(t, a.Init("t"))
assert.Equal(t, a.(*mockHook1).mockString, "t")
var hoo interface{} = &mockWrongHook{}
a, ok := hoo.(Hook)
assert.False(t, ok)
}
func initTestMeta(t *testing.T, node *QueryNode, collectionID UniqueID, segmentID UniqueID, optional ...bool) {
schema := genTestCollectionSchema()
@ -160,6 +183,7 @@ func TestMain(m *testing.M) {
// NOTE: start pulsar and etcd before test
func TestQueryNode_Start(t *testing.T) {
localNode := newQueryNodeMock()
assert.Nil(t, localNode.queryHook)
localNode.Start()
<-localNode.queryNodeLoopCtx.Done()
localNode.Stop()

View File

@ -1,86 +0,0 @@
// Licensed to the LF AI & Data foundation under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package autoindex
import (
"fmt"
"strings"
//"strconv"
"github.com/milvus-io/milvus-proto/go-api/commonpb"
"github.com/sandertv/go-formula/v2"
)
const (
TopKKey = "topk"
)
var _ calculateFunc = (*function)(nil)
type calculateFunc interface {
calculate(params []*commonpb.KeyValuePair) (map[string]interface{}, error)
GetInputKey() string
GetOutputKey() string
}
type function struct {
f *formula.Formula
input string
inputKey string
outputKey string
}
func newFunction(stmt string) (*function, error) {
input, output, expr, err := parseAssignment(stmt)
if err != nil {
return nil, fmt.Errorf("parse function failed, wrong format:%w", err)
}
f, err := formula.New(expr)
if err != nil {
return nil, fmt.Errorf("parse function failed, wrong format:%w", err)
}
ret := &function{}
ret.f = f
ret.input = input
ret.inputKey = strings.TrimPrefix(input, VariablePrefix)
ret.outputKey = strings.TrimPrefix(output, VariablePrefix)
return ret, nil
}
func (f *function) calculate(params []*commonpb.KeyValuePair) (map[string]interface{}, error) {
inputValue, err := getInt64FromParams(params, f.inputKey)
if err != nil {
return nil, err
}
inputVar := formula.Var(f.input, inputValue)
outputValue, err := f.f.Eval(inputVar)
if err != nil {
return nil, fmt.Errorf("calculate failed:%w", err)
}
ret := make(map[string]interface{})
ret[f.outputKey] = int64(outputValue)
return ret, nil
}
func (f *function) GetInputKey() string {
return f.inputKey
}
func (f *function) GetOutputKey() string {
return f.outputKey
}

View File

@ -1,118 +0,0 @@
// Licensed to the LF AI & Data foundation under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package autoindex
import (
"math"
"testing"
"github.com/milvus-io/milvus-proto/go-api/commonpb"
"github.com/stretchr/testify/assert"
)
func TestAutoIndexFunctionParse(t *testing.T) {
var f calculateFunc
var err error
validFuncStrs := []string{
" __output = __input * 2 + 1",
" __output = __input",
" __output = 1.5 * pow(__input, 1.2) + 40",
}
for _, funcStr := range validFuncStrs {
f, err = newFunction(funcStr)
assert.NoError(t, err)
assert.NotNil(t, f)
assert.Equal(t, "input", f.GetInputKey())
assert.Equal(t, "output", f.GetOutputKey())
}
invalidFuncStrs := []string{
"",
"{",
" output = __input * 2 + 1",
" __output __input * 2 + 1",
" _output = __input * 2 + 1",
}
for _, funcStr := range invalidFuncStrs {
f, err = newFunction(funcStr)
assert.Error(t, err)
assert.Nil(t, f)
}
}
func TestAutoIndexFunctionCalculate(t *testing.T) {
var params []*commonpb.KeyValuePair
inputKey := "input"
outputKey := "output"
params = append(params, &commonpb.KeyValuePair{
Key: inputKey,
Value: "10",
})
var f calculateFunc
var err error
t.Run("function1", func(t *testing.T) {
funcStr := "__output = 4 * __input + 5"
f, err = newFunction(funcStr)
assert.NoError(t, err)
tValue, err := f.calculate(params)
assert.NoError(t, err)
assert.Equal(t, int64(4*10+5), tValue[outputKey].(int64))
})
t.Run("function2", func(t *testing.T) {
funcStr := "__output = 4 * pow(__input,2) + 6"
f, err = newFunction(funcStr)
assert.NoError(t, err)
tValue, err := f.calculate(params)
assert.NoError(t, err)
targetV := int64(4*math.Pow(10, 2) + 6)
assert.Equal(t, targetV, tValue[outputKey].(int64))
})
t.Run("function3", func(t *testing.T) {
funcStr := "__output = __input"
f, err = newFunction(funcStr)
assert.NoError(t, err)
tValue, err := f.calculate(params)
assert.NoError(t, err)
assert.Equal(t, int64(10), tValue[outputKey].(int64))
})
t.Run("function4", func(t *testing.T) {
funcStr := "__output_2 = 4 * pow(__input, 2) + 6"
f, err = newFunction(funcStr)
assert.NoError(t, err)
tValue, err := f.calculate(params)
assert.NoError(t, err)
targetV := int64(4*math.Pow(10, 2) + 6)
assert.Equal(t, targetV, tValue["output_2"].(int64))
})
t.Run("function5", func(t *testing.T) {
funcStr := "__output_3 = 1.5 * exp(__input*0.1) + 3"
f, err = newFunction(funcStr)
assert.NoError(t, err)
tValue, err := f.calculate(params)
assert.NoError(t, err)
targetV := int64(1.5*math.Exp(10*0.1) + 3)
assert.Equal(t, targetV, tValue["output_3"].(int64))
})
}

View File

@ -1,164 +0,0 @@
// Licensed to the LF AI & Data foundation under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package autoindex
import (
"encoding/json"
"fmt"
"github.com/milvus-io/milvus-proto/go-api/commonpb"
)
var _ Calculator = (*methodPieceWise)(nil)
var _ Calculator = (*methodNormal)(nil)
type Calculator interface {
Calculate(params []*commonpb.KeyValuePair) (map[string]interface{}, error)
}
type methodPieceWise struct {
bp []float64
functions []calculateFunc
bpKey string
}
func (m *methodPieceWise) Calculate(params []*commonpb.KeyValuePair) (map[string]interface{}, error) {
bpValue, err := getInt64FromParams(params, m.bpKey)
if err != nil {
return nil, err
}
idx := 0
for _, p := range m.bp {
if bpValue < int64(p) {
break
}
idx++
}
if idx >= len(m.functions) {
// can not happen
return nil, fmt.Errorf("calculate failed, methodPeiceWise functions size not match")
}
f := m.functions[idx]
retMap, err := f.calculate(params)
if err != nil {
return nil, err
}
return retMap, nil
}
func newMethodPieceWise(jsonStr string) (*methodPieceWise, error) {
valueMap := make(map[string]interface{})
err := json.Unmarshal([]byte(jsonStr), &valueMap)
if err != nil {
return nil, fmt.Errorf("newMethodPieceWise failed:%w", err)
}
return newMethodPieceWiseFromMap(valueMap)
}
func newMethodPieceWiseFromMap(values map[string]interface{}) (*methodPieceWise, error) {
var err error
bpValue, ok := values["bp"]
if !ok {
return nil, fmt.Errorf("parse piecewise function failed, bp not specified")
}
bpSlice, ok := bpValue.([]interface{})
if !ok {
return nil, fmt.Errorf("parse piecewise bp failed, bp in wrong format")
}
var bpValues []float64
for _, bpV := range bpSlice {
bpFloat, ok := bpV.(float64)
if !ok {
return nil, fmt.Errorf("parse piecewise bp failed, bp in wrong format")
}
bpValues = append(bpValues, bpFloat)
}
funcs, ok := values["functions"]
if !ok {
return nil, fmt.Errorf("parse piecewise function failed, functions not specified")
}
funcStrSlice, ok := funcs.([]interface{})
if !ok {
return nil, fmt.Errorf("parse piecewise function failed, functions in wrong format")
}
var functions []calculateFunc
for _, funcValue := range funcStrSlice {
funcStr, ok := funcValue.(string)
if !ok {
return nil, fmt.Errorf("parse piecewise function failed, function in wrong format")
}
var f calculateFunc
f, err = newFunction(funcStr)
if err != nil {
return nil, err
}
functions = append(functions, f)
}
if len(bpValues)+1 != len(functions) {
return nil, fmt.Errorf("parse piecewise function failed, function size not match to bp size")
}
ret := &methodPieceWise{
bp: bpValues,
functions: functions,
bpKey: functions[0].GetInputKey(),
}
return ret, nil
}
type methodNormal struct {
function calculateFunc
}
func (m *methodNormal) Calculate(params []*commonpb.KeyValuePair) (map[string]interface{}, error) {
retMap, err := m.function.calculate(params)
if err != nil {
return nil, err
}
return retMap, nil
}
func newMethodNormal(jsonStr string) (*methodNormal, error) {
valueMap := make(map[string]interface{})
err := json.Unmarshal([]byte(jsonStr), &valueMap)
if err != nil {
return nil, fmt.Errorf("newMethodNormal failed:%w", err)
}
return newMethodNormalFromMap(valueMap)
}
func newMethodNormalFromMap(values map[string]interface{}) (*methodNormal, error) {
var err error
funcValue, ok := values["function"]
if !ok {
return nil, fmt.Errorf("parse normal method failed, function not specified")
}
funcStr, ok := funcValue.(string)
if !ok {
return nil, fmt.Errorf("parse normal method failed, function in wrong format")
}
var f calculateFunc
f, err = newFunction(funcStr)
if err != nil {
return nil, err
}
ret := &methodNormal{
function: f,
}
return ret, nil
}

View File

@ -1,154 +0,0 @@
// Licensed to the LF AI & Data foundation under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package autoindex
import (
"encoding/json"
"math"
"testing"
"github.com/milvus-io/milvus-proto/go-api/commonpb"
"github.com/stretchr/testify/assert"
)
func TestAutoIndexMethodParse(t *testing.T) {
var err error
json1 := `{
"function": "__output = __input * 10 + 5"
}`
m1, err := newMethodNormal(json1)
assert.NoError(t, err)
assert.NotNil(t, m1)
assert.NotNil(t, m1.function)
json2 := `{
"bp": [10, 200],
"functions": [
"__output = __input",
"__output = 10 * __input + 5",
"__output = pow(__input, 1)"
]
}`
m2, err := newMethodPieceWise(json2)
assert.NoError(t, err)
assert.NotNil(t, m2)
assert.NotNil(t, m2.functions)
assert.Equal(t, 2, len(m2.bp))
assert.Equal(t, 3, len(m2.functions))
assert.Equal(t, "input", m2.bpKey)
invalid1JSONS := []string{
"",
`{}`,
`{"": 1, "func": ""}`,
`{"bp": [1,2], "function": ""}`,
`{"bp": 1, "function": "xxx"}`,
}
invalid2JSONS := []string{
"",
`{}`,
`{"bp": 2}`,
`{"bp": [2], "func": ""}`,
`{"bp": [1,2], "function": ""}`,
`{"functions": "xxx"}`,
`{
"bp": [10, 200],
"functions": [
"__output = __input",
"__output = 10 * __input + 5",
]
}`,
}
var m Calculator
for _, jsonStr := range invalid1JSONS {
m, err = newMethodNormal(jsonStr)
assert.NotNil(t, err)
assert.Nil(t, m)
}
for _, jsonStr := range invalid2JSONS {
m, err = newMethodPieceWise(jsonStr)
assert.NotNil(t, err)
assert.Nil(t, m)
}
}
func TestAutoIndexMethodCalculate(t *testing.T) {
var err error
inputKey := "input"
outputKey := "output"
var params []*commonpb.KeyValuePair
params = append(params, &commonpb.KeyValuePair{
Key: inputKey,
Value: "10",
})
var method Calculator
t.Run("methodNormal", func(t *testing.T) {
jsonStr := `{
"function": "__output = 3 * pow(__input, 2) + 5"
}`
method, err = newMethodNormal(jsonStr)
assert.NoError(t, err)
targetV := int64(3*math.Pow(10, 2) + 5)
expMap := make(map[string]interface{})
expMap[outputKey] = targetV
expJSON, err := json.Marshal(expMap)
expJSONStr := string(expJSON)
assert.NoError(t, err)
ret, err := method.Calculate(params)
assert.NoError(t, err)
targetJSON, err := json.Marshal(ret)
assert.NoError(t, err)
targetJSONStr := string(targetJSON)
assert.Equal(t, expJSONStr, targetJSONStr)
})
t.Run("methodPieceWise", func(t *testing.T) {
jsonStr := `{
"bp": [10, 50],
"functions": [
"__output = __input",
"__output = 3.0*pow(__input,2) + 5",
"__output = 10 * __input + 5"
]
}`
method, err = newMethodPieceWise(jsonStr)
assert.NoError(t, err)
targetV := int64(3*math.Pow(10, 2) + 5)
expMap := make(map[string]interface{})
expMap[outputKey] = targetV
expJSON, err := json.Marshal(expMap)
expJSONStr := string(expJSON)
assert.NoError(t, err)
ret, err := method.Calculate(params)
assert.NoError(t, err)
targetJSON, err := json.Marshal(ret)
assert.NoError(t, err)
targetJSONStr := string(targetJSON)
assert.Equal(t, expJSONStr, targetJSONStr)
})
}

View File

@ -1,87 +0,0 @@
// Licensed to the LF AI & Data foundation under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package autoindex
import (
"fmt"
"strconv"
"sync"
"encoding/json"
)
type Parser struct {
rw sync.RWMutex
methods sync.Map // map of level to Calculator
}
func NewParser() *Parser {
return &Parser{
methods: sync.Map{},
}
}
func (p *Parser) InitFromJSONStr(value string) error {
valueMap := make(map[string]interface{})
err := json.Unmarshal([]byte(value), &valueMap)
if err != nil {
return fmt.Errorf("init autoindex parser failed:%w", err)
}
return p.InitFromMap(valueMap)
}
func (p *Parser) InitFromMap(values map[string]interface{}) error {
p.rw.Lock()
defer p.rw.Unlock()
p.methods = sync.Map{}
var err error
var cnt int
for levelStr, value := range values {
valueMap, ok := value.(map[string]interface{})
if !ok {
return fmt.Errorf("parse params failed, wrong format")
}
var level int
level, err = strconv.Atoi(levelStr)
if err != nil {
return fmt.Errorf("parse level failed, woring format")
}
var method Calculator
method, err = newMethodNormalFromMap(valueMap)
if err != nil {
method, err = newMethodPieceWiseFromMap(valueMap)
}
if err != nil {
return fmt.Errorf("parse method failed %w", err)
}
p.methods.Store(level, method)
cnt++
}
if cnt == 0 {
return fmt.Errorf("parse method failed: empty")
}
return nil
}
func (p *Parser) GetMethodByLevel(level int) (Calculator, bool) {
m, ok := p.methods.Load(level)
if !ok {
return nil, false
}
return m.(Calculator), true
}

View File

@ -1,143 +0,0 @@
package autoindex
import (
"encoding/json"
"math"
"testing"
"github.com/milvus-io/milvus-proto/go-api/commonpb"
"github.com/stretchr/testify/assert"
)
func TestAutoIndexParser_Parse(t *testing.T) {
jsonStr := `
{
"1": {
"function": "__output = 3*__input + 4"
},
"2": {
"bp": [10, 200],
"functions": [
"__output = __input + 4",
"__output = 3*__input + 4",
"__output = pow(__input, 2) + 4"
]
},
"3": {
"bp": [10, 300],
"functions": [
"__output = __input + 4",
"__output = 2*__input + 3",
"__output = pow(__input, 1.2) + 4"
]
}
}`
parser := NewParser()
err := parser.InitFromJSONStr(jsonStr)
assert.NoError(t, err)
invalid1JSONS := []string{
`{}`,
`{"1":xxx}`,
`{
"1": {
"func": "{"
},
"2": x
}`,
`{
"1": {
"function": "{\"funcID\": 3, \"cof1\": 3,\"cof2\": 4,\"cof3\": 5}"
},
"2": x
}`,
`{"": 1}`,
`{"": 1, "func": ""}`,
`{"": 1, "function": ""}`,
`{1, "function": "xxx"}`,
}
for _, jsonStr := range invalid1JSONS {
err := parser.InitFromJSONStr(jsonStr)
assert.NotNil(t, err)
}
}
func TestAutoIndexParser_GetMethodByLevel(t *testing.T) {
jsonStr := `
{
"1": {
"function": "__output = __input"
},
"2": {
"bp": [10, 50],
"functions": [
"__output = __input",
"__output = 3.0*pow(__input,2) + 5",
"__output = 10 * __input + 5"
]
},
"3": {
"bp": [10, 300],
"functions": [
"__output = 3.0*pow(__input,2) + 5",
"__output = 10 * __input + 5",
"__output = __input"
]
}
}`
var err error
parser := NewParser()
err = parser.InitFromJSONStr(jsonStr)
assert.NoError(t, err)
inputKey := "input"
outputKey := "output"
var params []*commonpb.KeyValuePair
params = append(params, &commonpb.KeyValuePair{
Key: inputKey,
Value: "10",
})
assertValueMapEqual := func(source, target map[string]interface{}) {
expJSON, err := json.Marshal(source)
expJSONStr := string(expJSON)
assert.NoError(t, err)
targetJSON, err := json.Marshal(target)
assert.NoError(t, err)
targetJSONStr := string(targetJSON)
assert.Equal(t, expJSONStr, targetJSONStr)
}
normalTargetValues := []int64{
10,
int64(3*math.Pow(10, 2) + 5),
int64(10*10 + 5),
}
normalLevels := []int{1, 2, 3}
for i, l := range normalLevels {
targetV := normalTargetValues[i]
expMap := make(map[string]interface{})
expMap[outputKey] = targetV
m, exist := parser.GetMethodByLevel(l)
assert.NotNil(t, m)
assert.True(t, exist)
ret, err := m.Calculate(params)
assert.NoError(t, err)
assertValueMapEqual(expMap, ret)
}
invalidLevels := []int{-1, 0, 4}
for _, l := range invalidLevels {
m, exist := parser.GetMethodByLevel(l)
assert.Nil(t, m)
assert.False(t, exist)
}
}

View File

@ -1,113 +0,0 @@
// Licensed to the LF AI & Data foundation under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package autoindex
import (
"fmt"
"strconv"
"strings"
"go/ast"
"go/parser"
//"encoding/json"
"github.com/milvus-io/milvus-proto/go-api/commonpb"
"github.com/milvus-io/milvus/internal/util/funcutil"
)
const (
VariablePrefix = "__"
)
type identVisitor struct {
input string
valid bool
}
func (v *identVisitor) Visit(n ast.Node) ast.Visitor {
if n == nil {
return nil
}
switch d := n.(type) {
case *ast.Ident:
if strings.HasPrefix(d.Name, VariablePrefix) {
if v.valid {
if v.input != d.Name {
v.valid = false
return nil
}
} else {
v.input = d.Name
v.valid = true
}
}
}
return v
}
func parseIdentFromExpr(expression string) (string, error) {
expr, err := parser.ParseExpr(expression)
if err != nil {
return "", fmt.Errorf("parse input from expression failed: %v", err)
}
var x identVisitor
ast.Walk(&x, expr)
if !x.valid {
return "", fmt.Errorf("parse input from expression failed: number of input variable should be 1")
}
return x.input, nil
}
func parseAssignment(stmt string) (input string, output string, expr string, err error) {
defer func() {
if err != nil {
input = ""
output = ""
expr = ""
}
}()
exprs := strings.Split(stmt, "=")
if len(exprs) != 2 {
err = fmt.Errorf("parse assignment stmt failed, wrong format")
return
}
output, err = parseIdentFromExpr(exprs[0])
if err != nil {
err = fmt.Errorf("parse assignment stmt failed, wrong lvalue format:%w", err)
return
}
expr = exprs[1]
input, err = parseIdentFromExpr(expr)
if err != nil {
err = fmt.Errorf("parse assignment stmt failed, wrong rvalue format:%w", err)
return
}
return
}
func getInt64FromParams(params []*commonpb.KeyValuePair, key string) (int64, error) {
valueStr, err := funcutil.GetAttrByKeyFromRepeatedKV(key, params)
if err != nil {
return 0, fmt.Errorf("%s not found in search_params", key)
}
value, err := strconv.ParseInt(valueStr, 0, 64)
if err != nil {
return 0, fmt.Errorf("%s [%s] is invalid", key, valueStr)
}
return value, nil
}

View File

@ -1,106 +0,0 @@
package autoindex
import (
"testing"
"github.com/milvus-io/milvus-proto/go-api/commonpb"
"github.com/sandertv/go-formula/v2"
"github.com/stretchr/testify/assert"
)
func TestAutoIndexUtil_getInt64FromParams(t *testing.T) {
var params []*commonpb.KeyValuePair
params = append(params, &commonpb.KeyValuePair{
Key: TopKKey,
Value: "10",
})
t.Run("getInt64FromParams1", func(t *testing.T) {
topK, err := getInt64FromParams(params, TopKKey)
assert.NoError(t, err)
assert.Equal(t, int64(10), topK)
})
t.Run("getInt64FromParams2", func(t *testing.T) {
topK, err := getInt64FromParams(params, "")
assert.Error(t, err)
assert.Equal(t, int64(0), topK)
})
t.Run("getInt64FromParams3", func(t *testing.T) {
var params []*commonpb.KeyValuePair
params = append(params, &commonpb.KeyValuePair{
Key: TopKKey,
Value: "x",
})
topK, err := getInt64FromParams(params, TopKKey)
assert.Error(t, err)
assert.Equal(t, int64(0), topK)
})
}
func TestAutoIndexUtil_parseAssignment(t *testing.T) {
t.Run("stmt1", func(t *testing.T) {
stmt := "__output = 1 *pow(__input * 1.1, 4) + __input * 2 + 2"
input, output, expr, err := parseAssignment(stmt)
assert.NoError(t, err)
assert.Equal(t, "__output", output)
assert.Equal(t, "__input", input)
f, err := formula.New(expr)
assert.NotNil(t, f)
assert.NoError(t, err)
})
t.Run("stmt2", func(t *testing.T) {
stmt := "__output 1 *pox(__input * 1.1, 4) + __input * 2 + 2"
input, output, expr, err := parseAssignment(stmt)
assert.Error(t, err)
assert.Equal(t, "", output)
assert.Equal(t, "", input)
assert.Equal(t, "", expr)
f, err := formula.New(expr)
assert.Nil(t, f)
assert.Error(t, err)
})
t.Run("stmt3", func(t *testing.T) {
stmt := "_output = 1 *pox(__input * 1.1, 4) + __input * 2 + 2"
input, output, expr, err := parseAssignment(stmt)
assert.Error(t, err)
assert.Equal(t, "", output)
assert.Equal(t, "", input)
assert.Equal(t, "", expr)
f, err := formula.New(expr)
assert.Nil(t, f)
assert.Error(t, err)
})
t.Run("stmt4", func(t *testing.T) {
stmt := "__output = 1 *pox(_topk * 1.1, 4) + __input * 2 + 2"
input, output, expr, err := parseAssignment(stmt)
assert.NoError(t, err)
assert.Equal(t, "__output", output)
assert.Equal(t, "__input", input)
f, err := formula.New(expr)
assert.NotNil(t, f)
assert.NoError(t, err)
inputVar := formula.Var(input, 1)
_, err = f.Eval(inputVar)
assert.Error(t, err)
})
t.Run("stmt5", func(t *testing.T) {
stmt := "__output = 1 *pox(_topK * 1.1, 4) + _topK1 * 2 + 2"
input, output, expr, err := parseAssignment(stmt)
assert.Error(t, err)
assert.Equal(t, "", output)
assert.Equal(t, "", input)
assert.Equal(t, "", expr)
f, err := formula.New(expr)
assert.Nil(t, f)
assert.Error(t, err)
})
}

View File

@ -42,7 +42,6 @@ type autoIndexConfig struct {
IndexType string
AutoIndexTypeName string
Parser *autoindex.Parser
}
func (p *autoIndexConfig) init(base *BaseTable) {
@ -70,7 +69,7 @@ func (p *autoIndexConfig) initParams() {
p.parseBuildParams(p.indexParamsStr)
p.SearchParamsYamlStr = p.Base.LoadWithDefault("autoIndex.params.search", "")
p.parseSearchParams(p.SearchParamsYamlStr)
p.AutoIndexTypeName = p.Base.LoadWithDefault("autoIndex.type", "")
p.extraParamsStr = p.Base.LoadWithDefault("autoIndex.params.extra", "")
p.parseExtraParams(p.extraParamsStr)
@ -99,24 +98,3 @@ func (p *autoIndexConfig) parseExtraParams(paramsStr string) {
panic(err2)
}
}
func (p *autoIndexConfig) parseSearchParams(paramsStr string) {
p.Parser = autoindex.NewParser()
err := p.Parser.InitFromJSONStr(paramsStr)
if err != nil {
err2 := fmt.Errorf("parse autoindex search params failed:%w", err)
panic(err2)
}
}
// GetSearchParamStrCalculator return a method which can calculate searchParams
func (p *autoIndexConfig) GetSearchParamStrCalculator(level int) autoindex.Calculator {
if !p.Enable {
return nil
}
m, ok := p.Parser.GetMethodByLevel(level)
if !ok {
return nil
}
return m
}

View File

@ -24,7 +24,6 @@ import (
"github.com/stretchr/testify/assert"
"github.com/milvus-io/milvus/internal/common"
"github.com/milvus-io/milvus/internal/util/autoindex"
)
const (
@ -90,58 +89,3 @@ func TestAutoIndexParams_build(t *testing.T) {
CParams.AutoIndexConfig.parseBuildParams(string(jsonStrBytes))
})
}
func TestAutoIndexParams_search1(t *testing.T) {
var CParams ComponentParam
CParams.Init()
CParams.AutoIndexConfig.Enable = true
var err error
indexMap := map[string]interface{}{
IndexTypeKey: "HNSW",
"M": 48,
"efConstruction": 500,
}
var jsonStrBytes []byte
jsonStrBytes, err = json.Marshal(indexMap)
assert.NoError(t, err)
CParams.AutoIndexConfig.parseBuildParams(string(jsonStrBytes))
jsonStr := `
{
"1": {
"function": "__output = 3*__input + 4"
},
"2": {
"bp": [10, 200],
"functions": [
"__output = __input + 4",
"__output = 3*__input + 4",
"__output = pow(__input, 2) + 4"
]
},
"3": {
"bp": [10, 300],
"functions": [
"__output = __input + 4",
"__output = 2*__input + 3",
"__output = pow(__input, 1.2) + 4"
]
}
}`
CParams.AutoIndexConfig.Parser = autoindex.NewParser()
CParams.AutoIndexConfig.Parser.InitFromJSONStr(jsonStr)
assert.NoError(t, err)
normalLevels := []int{1, 2, 3}
for _, l := range normalLevels {
m := CParams.AutoIndexConfig.GetSearchParamStrCalculator(l)
assert.NotNil(t, m)
}
invalidLevels := []int{-1, 0, 4}
for _, l := range invalidLevels {
m := CParams.AutoIndexConfig.GetSearchParamStrCalculator(l)
assert.Nil(t, m)
}
}

View File

@ -1033,6 +1033,7 @@ func (p *queryCoordConfig) initEnableRGAutoRecover() {
type queryNodeConfig struct {
Base *BaseTable
SoPath string
Alias string
QueryNodeIP string
QueryNodePort int64
@ -1088,6 +1089,7 @@ func (p *queryNodeConfig) init(base *BaseTable) {
p.Base = base
p.NodeID.Store(UniqueID(0))
p.initSoPath()
p.initFlowGraphMaxQueueLength()
p.initFlowGraphMaxParallelism()
@ -1126,6 +1128,10 @@ func (p *queryNodeConfig) InitAlias(alias string) {
p.Alias = alias
}
func (p *queryNodeConfig) initSoPath() {
p.SoPath = p.Base.LoadWithDefault("queryNode.soPath", "")
}
// advanced params
// stats
func (p *queryNodeConfig) initStatsPublishInterval() {