Add querynode plugin (#22379)

Signed-off-by: chasingegg <chao.gao@zilliz.com>
This commit is contained in:
Gao 2023-03-24 15:21:59 +08:00 committed by GitHub
parent ef93e24da7
commit 8b3e5189e1
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
35 changed files with 864 additions and 1879 deletions

1
go.mod
View File

@ -31,7 +31,6 @@ require (
github.com/panjf2000/ants/v2 v2.4.8
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

3
go.sum
View File

@ -708,8 +708,6 @@ github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb
github.com/ryanuber/columnize v2.1.0+incompatible/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=
@ -885,7 +883,6 @@ go.opentelemetry.io/proto/otlp v0.19.0 h1:IVN6GR+mhC4s5yfcTbmzHYODqvWAp3ZedA2SJP
go.opentelemetry.io/proto/otlp v0.19.0/go.mod h1:H7XAot3MsfNsj7EXtrA2q5xSNQ10UqI405h3+duxN4U=
go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE=
go.uber.org/atomic v1.6.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ=
go.uber.org/atomic v1.7.0 h1:ADUqmZGgLDDfbSL9ZmPxKTybcoEYHgpYfELNoN+7hsw=
go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc=
go.uber.org/atomic v1.10.0 h1:9qC72Qh0+3MqyJbAn8YU5xVq1frD8bn3JtD2oXtafVQ=
go.uber.org/atomic v1.10.0/go.mod h1:LUxbIzbOniOlMKjJjyPfpl4v+PKK2cNJn91OQbhoJI0=

View File

@ -292,6 +292,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

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

View File

@ -16,7 +16,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")
@ -104,10 +104,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
}
@ -126,7 +127,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

@ -167,7 +167,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

@ -454,7 +454,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, channelNum int) error {
retrieveReq := typeutil.Clone(t.RetrieveRequest)
retrieveReq.GetBase().TargetID = nodeID
req := &querypb.QueryRequest{

View File

@ -44,7 +44,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,7 @@ package proxy
import (
"context"
"encoding/json"
"fmt"
"regexp"
"strconv"
@ -21,7 +21,6 @@ import (
"github.com/milvus-io/milvus/internal/metrics"
"github.com/milvus-io/milvus/internal/types"
"github.com/milvus-io/milvus/internal/util/autoindex"
"github.com/milvus-io/milvus/internal/util/commonpbutil"
"github.com/milvus-io/milvus/internal/util/distance"
"github.com/milvus-io/milvus/internal/util/funcutil"
@ -100,62 +99,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.GetAsBool() {
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
}
paramsStr := Params.AutoIndexConfig.SearchParamsYamlStr.GetValue()
calculator := autoindex.GetSearchCalculator(paramsStr, 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)
@ -208,7 +151,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
}
@ -496,13 +439,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"
"fmt"
"strconv"
"strings"
@ -12,7 +11,6 @@ import (
"github.com/cockroachdb/errors"
"github.com/golang/protobuf/proto"
"github.com/milvus-io/milvus/internal/util/indexparamcheck"
"github.com/milvus-io/milvus/internal/util/paramtable"
"github.com/milvus-io/milvus/internal/util/typeutil"
"github.com/stretchr/testify/assert"
@ -1700,7 +1698,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")
}
)
@ -1958,207 +1956,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
//parseSearchParams
paramtable.Get().Save(Params.AutoIndexConfig.Enable.Key, "true")
paramtable.Get().Save(Params.AutoIndexConfig.IndexType.Key, indexparamcheck.IndexHNSW)
paramtable.Get().Save(Params.AutoIndexConfig.IndexParams.Key, "{}")
defer func() {
paramtable.Get().Reset(Params.AutoIndexConfig.Enable.Key)
paramtable.Get().Reset(Params.AutoIndexConfig.IndexType.Key)
paramtable.Get().Reset(Params.AutoIndexConfig.IndexParams.Key)
}()
buildParams := map[string]any{
common.MetricTypeKey: indexparamcheck.L2,
common.IndexTypeKey: indexparamcheck.IndexHNSW,
"M": 8,
"efConstruction": 50,
}
buildParamsJSONValue, err := json.Marshal(buildParams)
assert.NoError(t, err)
paramtable.Get().Save(Params.AutoIndexConfig.IndexParams.Key, string(buildParamsJSONValue))
defer paramtable.Get().Reset(Params.AutoIndexConfig.IndexParams.Key)
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"
]
}
}`
paramtable.Get().Save(Params.AutoIndexConfig.SearchParamsYamlStr.Key, jsonStr)
defer paramtable.Get().Reset(Params.AutoIndexConfig.SearchParamsYamlStr.Key)
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
}
func getSearchResultData(nq, topk int64) *schemapb.SearchResultData {
result := schemapb.SearchResultData{
NumQueries: nq,

View File

@ -298,7 +298,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, channelNum int) error {
req := &querypb.GetStatisticsRequest{
Req: g.GetStatisticsRequest,
DmlChannels: channelIDs,

View File

@ -155,14 +155,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/commonpbutil"
"github.com/milvus-io/milvus/internal/util/metricsinfo"
@ -772,11 +773,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)
@ -910,6 +912,44 @@ 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
}
segmentNum := cluster.GetSegmentNum() * 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{}{
"topk": qinfo.GetTopk(),
"search_param": qinfo.GetSearchParams(),
"segment_num": segmentNum,
}
err := node.queryHook.Run(paramMap)
if err != nil {
failRet.Status.Reason = err.Error()
return failRet, nil
}
qinfo.Topk = paramMap["topk"].(int64)
qinfo.SearchParams = paramMap["search_param"].(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,10 +19,12 @@ package querynode
import (
"context"
"encoding/json"
"fmt"
"math/rand"
"sync"
"testing"
"github.com/golang/protobuf/proto"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/mock"
"github.com/stretchr/testify/require"
@ -32,6 +34,7 @@ import (
"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/conc"
@ -39,6 +42,7 @@ import (
"github.com/milvus-io/milvus/internal/util/metricsinfo"
"github.com/milvus-io/milvus/internal/util/paramtable"
"github.com/milvus-io/milvus/internal/util/sessionutil"
"github.com/milvus-io/milvus/internal/util/typeutil"
)
func TestImpl_GetComponentStates(t *testing.T) {
@ -826,6 +830,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

@ -1482,6 +1482,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 {
@ -1552,22 +1621,28 @@ 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
}
simpleDSL, err2 := genDSLByIndexType(schema, indexType)
if err2 != nil {
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,
SerializedExprPlan: expr,
Nq: nq,
}, nil
}

View File

@ -32,6 +32,7 @@ import (
"fmt"
"os"
"path"
"plugin"
"runtime"
"runtime/debug"
"sync"
@ -39,11 +40,11 @@ import (
"time"
"unsafe"
"github.com/milvus-io/milvus/internal/mq/msgdispatcher"
"github.com/milvus-io/milvus-proto/go-api/commonpb"
"github.com/milvus-io/milvus/internal/config"
etcdkv "github.com/milvus-io/milvus/internal/kv/etcd"
"github.com/milvus-io/milvus/internal/log"
"github.com/milvus-io/milvus/internal/mq/msgdispatcher"
"github.com/milvus-io/milvus/internal/storage"
"github.com/milvus-io/milvus/internal/types"
"github.com/milvus-io/milvus/internal/util/conc"
@ -127,6 +128,8 @@ type QueryNode struct {
taskPool *conc.Pool
IsStandAlone bool
queryHook Hook
}
var queryNode *QueryNode = nil
@ -135,6 +138,39 @@ func GetQueryNode() *QueryNode {
return queryNode
}
type Hook interface {
Run(map[string]interface{}) error
Init(string) error
}
func initHook() (Hook, error) {
path := Params.QueryNodeCfg.SoPath.GetValue()
if path == "" {
return nil, fmt.Errorf("fail to set the 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.HookCfg.QueryNodePluginConfig.GetValue()); err != nil {
return nil, fmt.Errorf("fail to init configs for the hook, error: %s", err.Error())
}
return hoo, nil
}
// NewQueryNode will return a QueryNode with abnormal state.
func NewQueryNode(ctx context.Context, factory dependency.Factory) *QueryNode {
ctx1, cancel := context.WithCancel(ctx)
@ -147,6 +183,26 @@ func NewQueryNode(ctx context.Context, factory dependency.Factory) *QueryNode {
lifetime: lifetime.NewLifetime(commonpb.StateCode_Abnormal),
}
// init querynode plugin
var err error
queryNode.queryHook, err = initHook()
if err != nil {
log.Error(err.Error())
if Params.AutoIndexConfig.Enable.GetAsBool() {
panic(err)
}
}
onEvent := func() func(*config.Event) {
return func(event *config.Event) {
if queryNode.queryHook != nil {
if err := queryNode.queryHook.Init(event.Value); err != nil {
// refresh error, we could still use old config
log.Error("fail to refresh config, error: %s", zap.Error(err))
}
}
}
}()
Params.Watch(Params.HookCfg.QueryNodePluginConfig.Key, config.NewHandler("hook", onEvent))
queryNode.tSafeReplica = newTSafeReplica()
queryNode.scheduler = newTaskScheduler(ctx1, queryNode.tSafeReplica)

View File

@ -45,6 +45,29 @@ func setup() {
paramtable.Get().BaseTable.Save("etcd.metaSubPath", "querynode")
}
func TestInitHook(t *testing.T) {
paramtable.Get().Save(Params.QueryNodeCfg.SoPath.Key, "")
a, err := initHook()
assert.Nil(t, a)
assert.NotNil(t, err)
paramtable.Get().Save(Params.QueryNodeCfg.SoPath.Key, "/a/b/hook.so")
a, err = initHook()
assert.Nil(t, a)
assert.NotNil(t, err)
paramtable.Get().Save(Params.QueryNodeCfg.SoPath.Key, "")
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()
@ -138,6 +161,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

@ -1121,6 +1121,13 @@ func (sc *ShardCluster) GetSegmentInfos() []shardSegmentInfo {
return ret
}
func (sc *ShardCluster) GetSegmentNum() int {
sc.mut.RLock()
defer sc.mut.RUnlock()
ret := len(sc.segments)
return ret
}
func (sc *ShardCluster) getVersion() int64 {
return sc.version
}

View File

@ -1,127 +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"
"strconv"
"github.com/milvus-io/milvus/internal/util/funcutil"
)
type BigDataIndexExtraParams struct {
PQCodeBudgetGBRatio float64
BuildNumThreadsRatio float64
SearchCacheBudgetGBRatio float64
LoadNumThreadRatio float64
BeamWidthRatio float64
}
const (
BuildRatioKey = "build_ratio"
PrepareRatioKey = "prepare_ratio"
BeamWidthRatioKey = "beamwidth_ratio"
DefaultPQCodeBudgetGBRatio = 0.125
DefaultBuildNumThreadsRatio = 1.0
DefaultSearchCacheBudgetGBRatio = 0.10
DefaultLoadNumThreadRatio = 8.0
DefaultBeamWidthRatio = 4.0
)
func NewBigDataIndexExtraParams() *BigDataIndexExtraParams {
ret := &BigDataIndexExtraParams{
PQCodeBudgetGBRatio: DefaultPQCodeBudgetGBRatio,
BuildNumThreadsRatio: DefaultBuildNumThreadsRatio,
SearchCacheBudgetGBRatio: DefaultSearchCacheBudgetGBRatio,
LoadNumThreadRatio: DefaultLoadNumThreadRatio,
BeamWidthRatio: DefaultBeamWidthRatio,
}
return ret
}
func NewBigDataExtraParamsFromJSON(jsonStr string) (*BigDataIndexExtraParams, error) {
buffer, err := funcutil.JSONToMap(jsonStr)
if err != nil {
return nil, err
}
return NewBigDataExtraParamsFromMap(buffer)
}
func NewBigDataExtraParamsFromMap(value map[string]string) (*BigDataIndexExtraParams, error) {
ret := &BigDataIndexExtraParams{}
var err error
buildRatio, ok := value[BuildRatioKey]
if !ok {
ret.PQCodeBudgetGBRatio = DefaultPQCodeBudgetGBRatio
ret.BuildNumThreadsRatio = DefaultBuildNumThreadsRatio
} else {
valueMap1 := make(map[string]float64)
err = json.Unmarshal([]byte(buildRatio), &valueMap1)
if err != nil {
return ret, err
}
PQCodeBudgetGBRatio, ok := valueMap1["pq_code_budget_gb"]
if !ok {
ret.PQCodeBudgetGBRatio = DefaultPQCodeBudgetGBRatio
} else {
ret.PQCodeBudgetGBRatio = PQCodeBudgetGBRatio
}
BuildNumThreadsRatio, ok := valueMap1["num_threads"]
if !ok {
ret.BuildNumThreadsRatio = DefaultBuildNumThreadsRatio
} else {
ret.BuildNumThreadsRatio = BuildNumThreadsRatio
}
}
prepareRatio, ok := value[PrepareRatioKey]
if !ok {
ret.SearchCacheBudgetGBRatio = DefaultSearchCacheBudgetGBRatio
ret.LoadNumThreadRatio = DefaultLoadNumThreadRatio
} else {
valueMap2 := make(map[string]float64)
err = json.Unmarshal([]byte(prepareRatio), &valueMap2)
if err != nil {
return ret, err
}
SearchCacheBudgetGBRatio, ok := valueMap2["search_cache_budget_gb"]
if !ok {
ret.SearchCacheBudgetGBRatio = DefaultSearchCacheBudgetGBRatio
} else {
ret.SearchCacheBudgetGBRatio = SearchCacheBudgetGBRatio
}
LoadNumThreadRatio, ok := valueMap2["num_threads"]
if !ok {
ret.LoadNumThreadRatio = DefaultLoadNumThreadRatio
} else {
ret.LoadNumThreadRatio = LoadNumThreadRatio
}
}
beamWidthRatioStr, ok := value[BeamWidthRatioKey]
if !ok {
ret.BeamWidthRatio = DefaultBeamWidthRatio
} else {
beamWidthRatio, err := strconv.ParseFloat(beamWidthRatioStr, 64)
if err != nil {
ret.BeamWidthRatio = DefaultBeamWidthRatio
} else {
ret.BeamWidthRatio = beamWidthRatio
}
}
return ret, nil
}

View File

@ -1,130 +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 (
"testing"
"github.com/stretchr/testify/assert"
)
func TestBigDataIndex_parse(t *testing.T) {
t.Run("parse normal", func(t *testing.T) {
mapString := make(map[string]string)
mapString[BuildRatioKey] = "{\"pq_code_budget_gb\": 0.125, \"num_threads\": 1}"
mapString[PrepareRatioKey] = "{\"search_cache_budget_gb\": 0.225, \"num_threads\": 8}"
extraParams, err := NewBigDataExtraParamsFromMap(mapString)
assert.NoError(t, err)
assert.Equal(t, 1.0, extraParams.BuildNumThreadsRatio)
assert.Equal(t, 8.0, extraParams.LoadNumThreadRatio)
assert.Equal(t, 0.125, extraParams.PQCodeBudgetGBRatio)
assert.Equal(t, 0.225, extraParams.SearchCacheBudgetGBRatio)
})
t.Run("parse with partial", func(t *testing.T) {
mapString := make(map[string]string)
mapString[PrepareRatioKey] = "{\"search_cache_budget_gb\": 0.225, \"num_threads\": 8}"
extraParams, err := NewBigDataExtraParamsFromMap(mapString)
assert.NoError(t, err)
assert.Equal(t, 1.0, extraParams.BuildNumThreadsRatio)
assert.Equal(t, 8.0, extraParams.LoadNumThreadRatio)
assert.Equal(t, 0.125, extraParams.PQCodeBudgetGBRatio)
assert.Equal(t, 0.225, extraParams.SearchCacheBudgetGBRatio)
})
t.Run("parse with empty", func(t *testing.T) {
mapString := make(map[string]string)
extraParams, err := NewBigDataExtraParamsFromMap(mapString)
assert.NoError(t, err)
assert.Equal(t, 1.0, extraParams.BuildNumThreadsRatio)
assert.Equal(t, 8.0, extraParams.LoadNumThreadRatio)
assert.Equal(t, 0.125, extraParams.PQCodeBudgetGBRatio)
assert.Equal(t, 0.10, extraParams.SearchCacheBudgetGBRatio)
})
t.Run("parse with nil", func(t *testing.T) {
extraParams, err := NewBigDataExtraParamsFromMap(nil)
assert.NoError(t, err)
assert.Equal(t, 1.0, extraParams.BuildNumThreadsRatio)
assert.Equal(t, 8.0, extraParams.LoadNumThreadRatio)
assert.Equal(t, 0.125, extraParams.PQCodeBudgetGBRatio)
assert.Equal(t, 0.10, extraParams.SearchCacheBudgetGBRatio)
})
t.Run("new from json normal", func(t *testing.T) {
jsonStr := `
{
"build_ratio": "{\"pq_code_budget_gb\": 0.125, \"num_threads\": 1}",
"prepare_ratio": "{\"search_cache_budget_gb\": 0.225, \"num_threads\": 8}",
"beamwidth_ratio": "8.0"
}
`
extraParams, err := NewBigDataExtraParamsFromJSON(jsonStr)
assert.NoError(t, err)
assert.Equal(t, 1.0, extraParams.BuildNumThreadsRatio)
assert.Equal(t, 8.0, extraParams.LoadNumThreadRatio)
assert.Equal(t, 0.125, extraParams.PQCodeBudgetGBRatio)
assert.Equal(t, 0.225, extraParams.SearchCacheBudgetGBRatio)
assert.Equal(t, 8.0, extraParams.BeamWidthRatio)
})
t.Run("new from json partial", func(t *testing.T) {
jsonStr := `
{
"build_ratio": "{\"pq_code_budget_gb\": 0.125, \"num_threads\": 1}"
}
`
extraParams, err := NewBigDataExtraParamsFromJSON(jsonStr)
assert.NoError(t, err)
assert.Equal(t, 1.0, extraParams.BuildNumThreadsRatio)
assert.Equal(t, 8.0, extraParams.LoadNumThreadRatio)
assert.Equal(t, 0.125, extraParams.PQCodeBudgetGBRatio)
assert.Equal(t, 0.10, extraParams.SearchCacheBudgetGBRatio)
assert.Equal(t, 4.0, extraParams.BeamWidthRatio)
})
t.Run("new from json empty", func(t *testing.T) {
jsonStr := `
{
}
`
extraParams, err := NewBigDataExtraParamsFromJSON(jsonStr)
assert.NoError(t, err)
assert.Equal(t, 1.0, extraParams.BuildNumThreadsRatio)
assert.Equal(t, 8.0, extraParams.LoadNumThreadRatio)
assert.Equal(t, 0.125, extraParams.PQCodeBudgetGBRatio)
assert.Equal(t, 0.10, extraParams.SearchCacheBudgetGBRatio)
assert.Equal(t, 4.0, extraParams.BeamWidthRatio)
})
t.Run("new from json invalid1", func(t *testing.T) {
jsonStr := `
{ x
}
`
_, err := NewBigDataExtraParamsFromJSON(jsonStr)
assert.Error(t, err)
})
t.Run("new from json invalid1", func(t *testing.T) {
jsonStr := `
""
`
_, err := NewBigDataExtraParamsFromJSON(jsonStr)
assert.Error(t, err)
})
}

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,101 +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
}
// GetSearchParamStrCalculator return a method which can calculate searchParams
func GetSearchCalculator(paramsStr string, level int) Calculator {
parser := NewParser()
err := parser.InitFromJSONStr(paramsStr)
if err != nil {
return nil
}
m, ok := parser.GetMethodByLevel(level)
if !ok {
return nil
}
return m
}

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

@ -17,11 +17,12 @@
package indexparams
import (
"encoding/json"
"fmt"
"strconv"
"unsafe"
"github.com/milvus-io/milvus/internal/util/autoindex"
"github.com/milvus-io/milvus/internal/util/funcutil"
"github.com/milvus-io/milvus/internal/util/hardware"
"github.com/milvus-io/milvus/internal/util/paramtable"
)
@ -52,6 +53,97 @@ func getRowDataSizeOfFloatVector(numRows int64, dim int64) int64 {
return int64(unsafe.Sizeof(floatValue)) * dim * numRows
}
type BigDataIndexExtraParams struct {
PQCodeBudgetGBRatio float64
BuildNumThreadsRatio float64
SearchCacheBudgetGBRatio float64
LoadNumThreadRatio float64
BeamWidthRatio float64
}
const (
BuildRatioKey = "build_ratio"
PrepareRatioKey = "prepare_ratio"
DefaultPQCodeBudgetGBRatio = 0.125
DefaultBuildNumThreadsRatio = 1.0
DefaultSearchCacheBudgetGBRatio = 0.10
DefaultLoadNumThreadRatio = 8.0
DefaultBeamWidthRatio = 4.0
)
func NewBigDataExtraParamsFromJSON(jsonStr string) (*BigDataIndexExtraParams, error) {
buffer, err := funcutil.JSONToMap(jsonStr)
if err != nil {
return nil, err
}
return NewBigDataExtraParamsFromMap(buffer)
}
func NewBigDataExtraParamsFromMap(value map[string]string) (*BigDataIndexExtraParams, error) {
ret := &BigDataIndexExtraParams{}
var err error
buildRatio, ok := value[BuildRatioKey]
if !ok {
ret.PQCodeBudgetGBRatio = DefaultPQCodeBudgetGBRatio
ret.BuildNumThreadsRatio = DefaultBuildNumThreadsRatio
} else {
valueMap1 := make(map[string]float64)
err = json.Unmarshal([]byte(buildRatio), &valueMap1)
if err != nil {
return ret, err
}
PQCodeBudgetGBRatio, ok := valueMap1["pq_code_budget_gb"]
if !ok {
ret.PQCodeBudgetGBRatio = DefaultPQCodeBudgetGBRatio
} else {
ret.PQCodeBudgetGBRatio = PQCodeBudgetGBRatio
}
BuildNumThreadsRatio, ok := valueMap1["num_threads"]
if !ok {
ret.BuildNumThreadsRatio = DefaultBuildNumThreadsRatio
} else {
ret.BuildNumThreadsRatio = BuildNumThreadsRatio
}
}
prepareRatio, ok := value[PrepareRatioKey]
if !ok {
ret.SearchCacheBudgetGBRatio = DefaultSearchCacheBudgetGBRatio
ret.LoadNumThreadRatio = DefaultLoadNumThreadRatio
} else {
valueMap2 := make(map[string]float64)
err = json.Unmarshal([]byte(prepareRatio), &valueMap2)
if err != nil {
return ret, err
}
SearchCacheBudgetGBRatio, ok := valueMap2["search_cache_budget_gb"]
if !ok {
ret.SearchCacheBudgetGBRatio = DefaultSearchCacheBudgetGBRatio
} else {
ret.SearchCacheBudgetGBRatio = SearchCacheBudgetGBRatio
}
LoadNumThreadRatio, ok := valueMap2["num_threads"]
if !ok {
ret.LoadNumThreadRatio = DefaultLoadNumThreadRatio
} else {
ret.LoadNumThreadRatio = LoadNumThreadRatio
}
}
beamWidthRatioStr, ok := value[BeamWidthRatioKey]
if !ok {
ret.BeamWidthRatio = DefaultBeamWidthRatio
} else {
beamWidthRatio, err := strconv.ParseFloat(beamWidthRatioStr, 64)
if err != nil {
ret.BeamWidthRatio = DefaultBeamWidthRatio
} else {
ret.BeamWidthRatio = beamWidthRatio
}
}
return ret, nil
}
// FillDiskIndexParams fill ratio params to index param on proxy node
// Which will be used to calculate build and load params
func FillDiskIndexParams(params *paramtable.ComponentParam, indexParams map[string]string) error {
@ -75,7 +167,7 @@ func FillDiskIndexParams(params *paramtable.ComponentParam, indexParams map[stri
if !ok {
return fmt.Errorf("index param search_list_size not exist")
}
extraParams, err := autoindex.NewBigDataExtraParamsFromJSON(params.AutoIndexConfig.ExtraParams.GetValue())
extraParams, err := NewBigDataExtraParamsFromJSON(params.AutoIndexConfig.ExtraParams.GetValue())
if err != nil {
return err
}

View File

@ -21,10 +21,8 @@ import (
"strconv"
"testing"
"github.com/stretchr/testify/assert"
"github.com/milvus-io/milvus/internal/util/autoindex"
"github.com/milvus-io/milvus/internal/util/paramtable"
"github.com/stretchr/testify/assert"
)
func TestDiskIndexParams(t *testing.T) {
@ -63,8 +61,8 @@ func TestDiskIndexParams(t *testing.T) {
params.Save(params.AutoIndexConfig.Enable.Key, "true")
mapString := make(map[string]string)
mapString[autoindex.BuildRatioKey] = "{\"pq_code_budget_gb\": 0.125, \"num_threads\": 1}"
mapString[autoindex.PrepareRatioKey] = "{\"search_cache_budget_gb\": 0.225, \"num_threads\": 4}"
mapString[BuildRatioKey] = "{\"pq_code_budget_gb\": 0.125, \"num_threads\": 1}"
mapString[PrepareRatioKey] = "{\"search_cache_budget_gb\": 0.225, \"num_threads\": 4}"
str, err := json.Marshal(mapString)
assert.NoError(t, err)
@ -122,8 +120,8 @@ func TestDiskIndexParams(t *testing.T) {
// IndexParams wrong
mapString := make(map[string]string)
mapString[autoindex.BuildRatioKey] = "{\"pq_code_budget_gb\": 0.125, \"num_threads\": 1}"
mapString[autoindex.PrepareRatioKey] = "{\"search_cache_budget_gb\": 0.225, \"num_threads\": 4}"
mapString[BuildRatioKey] = "{\"pq_code_budget_gb\": 0.125, \"num_threads\": 1}"
mapString[PrepareRatioKey] = "{\"search_cache_budget_gb\": 0.225, \"num_threads\": 4}"
str, err = json.Marshal(mapString)
assert.NoError(t, err)
@ -183,3 +181,177 @@ func TestDiskIndexParams(t *testing.T) {
assert.True(t, ok)
})
}
func TestBigDataIndex_parse(t *testing.T) {
t.Run("parse normal", func(t *testing.T) {
mapString := make(map[string]string)
mapString[BuildRatioKey] = "{\"pq_code_budget_gb\": 0.125, \"num_threads\": 1}"
mapString[PrepareRatioKey] = "{\"search_cache_budget_gb\": 0.225, \"num_threads\": 8}"
extraParams, err := NewBigDataExtraParamsFromMap(mapString)
assert.NoError(t, err)
assert.Equal(t, 1.0, extraParams.BuildNumThreadsRatio)
assert.Equal(t, 8.0, extraParams.LoadNumThreadRatio)
assert.Equal(t, 0.125, extraParams.PQCodeBudgetGBRatio)
assert.Equal(t, 0.225, extraParams.SearchCacheBudgetGBRatio)
})
t.Run("parse with build_ratio partial or wrong", func(t *testing.T) {
mapString := make(map[string]string)
mapString[BuildRatioKey] = "{\"pq_code_budget_gb\": 0.15}"
mapString[PrepareRatioKey] = "{\"search_cache_budget_gb\": 0.225, \"num_threads\": 8}"
extraParams, err := NewBigDataExtraParamsFromMap(mapString)
assert.NoError(t, err)
assert.Equal(t, 1.0, extraParams.BuildNumThreadsRatio)
assert.Equal(t, 8.0, extraParams.LoadNumThreadRatio)
assert.Equal(t, 0.15, extraParams.PQCodeBudgetGBRatio)
assert.Equal(t, 0.225, extraParams.SearchCacheBudgetGBRatio)
mapString = make(map[string]string)
mapString[BuildRatioKey] = "{\"num_threads\": 2}"
mapString[PrepareRatioKey] = "{\"search_cache_budget_gb\": 0.225, \"num_threads\": 8}"
extraParams, err = NewBigDataExtraParamsFromMap(mapString)
assert.NoError(t, err)
assert.Equal(t, 2.0, extraParams.BuildNumThreadsRatio)
assert.Equal(t, 8.0, extraParams.LoadNumThreadRatio)
assert.Equal(t, 0.125, extraParams.PQCodeBudgetGBRatio)
assert.Equal(t, 0.225, extraParams.SearchCacheBudgetGBRatio)
mapString = make(map[string]string)
mapString[BuildRatioKey] = "{\"num_threads\": 2"
mapString[PrepareRatioKey] = "{\"search_cache_budget_gb\": 0.225, \"num_threads\": 8}"
extraParams, err = NewBigDataExtraParamsFromMap(mapString)
assert.Error(t, err)
})
t.Run("parse with prepare_ratio partial or wrong", func(t *testing.T) {
mapString := make(map[string]string)
mapString[BuildRatioKey] = "{\"pq_code_budget_gb\": 0.125, \"num_threads\": 1}"
mapString[PrepareRatioKey] = "{\"search_cache_budget_gb\": 0.25}"
extraParams, err := NewBigDataExtraParamsFromMap(mapString)
assert.NoError(t, err)
assert.Equal(t, 1.0, extraParams.BuildNumThreadsRatio)
assert.Equal(t, 8.0, extraParams.LoadNumThreadRatio)
assert.Equal(t, 0.125, extraParams.PQCodeBudgetGBRatio)
assert.Equal(t, 0.25, extraParams.SearchCacheBudgetGBRatio)
mapString = make(map[string]string)
mapString[BuildRatioKey] = "{\"pq_code_budget_gb\": 0.125, \"num_threads\": 1}"
mapString[PrepareRatioKey] = "{\"num_threads\": 4}"
extraParams, err = NewBigDataExtraParamsFromMap(mapString)
assert.NoError(t, err)
assert.Equal(t, 1.0, extraParams.BuildNumThreadsRatio)
assert.Equal(t, 4.0, extraParams.LoadNumThreadRatio)
assert.Equal(t, 0.125, extraParams.PQCodeBudgetGBRatio)
assert.Equal(t, 0.10, extraParams.SearchCacheBudgetGBRatio)
mapString = make(map[string]string)
mapString[BuildRatioKey] = "{\"pq_code_budget_gb\": 0.125, \"num_threads\": 1}"
mapString[PrepareRatioKey] = "{\"search_cache_budget_gb\": 0.225"
extraParams, err = NewBigDataExtraParamsFromMap(mapString)
assert.Error(t, err)
})
t.Run("parse with beamwidth wrong", func(t *testing.T) {
mapString := make(map[string]string)
mapString[BeamWidthRatioKey] = "aa"
extraParams, err := NewBigDataExtraParamsFromMap(mapString)
assert.NoError(t, err)
assert.Equal(t, 1.0, extraParams.BuildNumThreadsRatio)
assert.Equal(t, 8.0, extraParams.LoadNumThreadRatio)
assert.Equal(t, 0.125, extraParams.PQCodeBudgetGBRatio)
assert.Equal(t, 0.10, extraParams.SearchCacheBudgetGBRatio)
})
t.Run("parse with partial", func(t *testing.T) {
mapString := make(map[string]string)
mapString[PrepareRatioKey] = "{\"search_cache_budget_gb\": 0.225, \"num_threads\": 8}"
extraParams, err := NewBigDataExtraParamsFromMap(mapString)
assert.NoError(t, err)
assert.Equal(t, 1.0, extraParams.BuildNumThreadsRatio)
assert.Equal(t, 8.0, extraParams.LoadNumThreadRatio)
assert.Equal(t, 0.125, extraParams.PQCodeBudgetGBRatio)
assert.Equal(t, 0.225, extraParams.SearchCacheBudgetGBRatio)
})
t.Run("parse with empty", func(t *testing.T) {
mapString := make(map[string]string)
extraParams, err := NewBigDataExtraParamsFromMap(mapString)
assert.NoError(t, err)
assert.Equal(t, 1.0, extraParams.BuildNumThreadsRatio)
assert.Equal(t, 8.0, extraParams.LoadNumThreadRatio)
assert.Equal(t, 0.125, extraParams.PQCodeBudgetGBRatio)
assert.Equal(t, 0.10, extraParams.SearchCacheBudgetGBRatio)
})
t.Run("parse with nil", func(t *testing.T) {
extraParams, err := NewBigDataExtraParamsFromMap(nil)
assert.NoError(t, err)
assert.Equal(t, 1.0, extraParams.BuildNumThreadsRatio)
assert.Equal(t, 8.0, extraParams.LoadNumThreadRatio)
assert.Equal(t, 0.125, extraParams.PQCodeBudgetGBRatio)
assert.Equal(t, 0.10, extraParams.SearchCacheBudgetGBRatio)
})
t.Run("new from json normal", func(t *testing.T) {
jsonStr := `
{
"build_ratio": "{\"pq_code_budget_gb\": 0.125, \"num_threads\": 1}",
"prepare_ratio": "{\"search_cache_budget_gb\": 0.225, \"num_threads\": 8}",
"beamwidth_ratio": "8.0"
}
`
extraParams, err := NewBigDataExtraParamsFromJSON(jsonStr)
assert.NoError(t, err)
assert.Equal(t, 1.0, extraParams.BuildNumThreadsRatio)
assert.Equal(t, 8.0, extraParams.LoadNumThreadRatio)
assert.Equal(t, 0.125, extraParams.PQCodeBudgetGBRatio)
assert.Equal(t, 0.225, extraParams.SearchCacheBudgetGBRatio)
assert.Equal(t, 8.0, extraParams.BeamWidthRatio)
})
t.Run("new from json partial", func(t *testing.T) {
jsonStr := `
{
"build_ratio": "{\"pq_code_budget_gb\": 0.125, \"num_threads\": 1}"
}
`
extraParams, err := NewBigDataExtraParamsFromJSON(jsonStr)
assert.NoError(t, err)
assert.Equal(t, 1.0, extraParams.BuildNumThreadsRatio)
assert.Equal(t, 8.0, extraParams.LoadNumThreadRatio)
assert.Equal(t, 0.125, extraParams.PQCodeBudgetGBRatio)
assert.Equal(t, 0.10, extraParams.SearchCacheBudgetGBRatio)
assert.Equal(t, 4.0, extraParams.BeamWidthRatio)
})
t.Run("new from json empty", func(t *testing.T) {
jsonStr := `
{
}
`
extraParams, err := NewBigDataExtraParamsFromJSON(jsonStr)
assert.NoError(t, err)
assert.Equal(t, 1.0, extraParams.BuildNumThreadsRatio)
assert.Equal(t, 8.0, extraParams.LoadNumThreadRatio)
assert.Equal(t, 0.125, extraParams.PQCodeBudgetGBRatio)
assert.Equal(t, 0.10, extraParams.SearchCacheBudgetGBRatio)
assert.Equal(t, 4.0, extraParams.BeamWidthRatio)
})
t.Run("new from json invalid1", func(t *testing.T) {
jsonStr := `
{ x
}
`
_, err := NewBigDataExtraParamsFromJSON(jsonStr)
assert.Error(t, err)
})
t.Run("new from json invalid1", func(t *testing.T) {
jsonStr := `
""
`
_, err := NewBigDataExtraParamsFromJSON(jsonStr)
assert.Error(t, err)
})
}

View File

@ -25,11 +25,10 @@ import (
type autoIndexConfig struct {
Enable ParamItem `refreshable:"true"`
IndexParams ParamItem `refreshable:"true"`
ExtraParams ParamItem `refreshable:"true"`
SearchParamsYamlStr ParamItem `refreshable:"true"`
IndexType ParamItem `refreshable:"true"`
AutoIndexTypeName ParamItem `refreshable:"true"`
IndexParams ParamItem `refreshable:"true"`
ExtraParams ParamItem `refreshable:"true"`
IndexType ParamItem `refreshable:"true"`
AutoIndexTypeName ParamItem `refreshable:"true"`
}
func (p *autoIndexConfig) init(base *BaseTable) {
@ -65,12 +64,6 @@ func (p *autoIndexConfig) init(base *BaseTable) {
}
p.IndexType.Init(base.mgr)
p.SearchParamsYamlStr = ParamItem{
Key: "autoIndex.params.search",
Version: "2.2.0",
}
p.SearchParamsYamlStr.Init(base.mgr)
p.AutoIndexTypeName = ParamItem{
Key: "autoIndex.type",
Version: "2.2.0",

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 (
@ -91,58 +90,3 @@ func TestAutoIndexParams_build(t *testing.T) {
// CParams.Save(CParams.AutoIndexConfig.IndexParams.Key, string(jsonStrBytes))
// })
}
func TestAutoIndexParams_search1(t *testing.T) {
var CParams ComponentParam
CParams.Init()
CParams.Save(CParams.AutoIndexConfig.Enable.Key, "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.Save(CParams.AutoIndexConfig.IndexParams.Key, 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"
]
}
}`
parser := autoindex.NewParser()
parser.InitFromJSONStr(jsonStr)
assert.NoError(t, err)
normalLevels := []int{1, 2, 3}
for _, l := range normalLevels {
m, _ := parser.GetMethodByLevel(l)
assert.NotNil(t, m)
}
invalidLevels := []int{-1, 0, 4}
for _, l := range invalidLevels {
m, _ := parser.GetMethodByLevel(l)
assert.Nil(t, m)
}
}

View File

@ -117,7 +117,7 @@ func (p *ComponentParam) init() {
p.IndexNodeCfg.init(&p.BaseTable)
p.HTTPCfg.init(&p.BaseTable)
p.LogCfg.init(&p.BaseTable)
p.HookCfg.init()
p.HookCfg.init(&p.BaseTable)
p.RootCoordGrpcServerCfg.Init("rootCoord", &p.BaseTable)
p.ProxyGrpcServerCfg.Init("proxy", &p.BaseTable)
@ -1302,6 +1302,8 @@ func (p *queryCoordConfig) init(base *BaseTable) {
// /////////////////////////////////////////////////////////////////////////////
// --- querynode ---
type queryNodeConfig struct {
SoPath ParamItem `refreshable:"false"`
FlowGraphMaxQueueLength ParamItem `refreshable:"false"`
FlowGraphMaxParallelism ParamItem `refreshable:"false"`
@ -1344,6 +1346,13 @@ type queryNodeConfig struct {
}
func (p *queryNodeConfig) init(base *BaseTable) {
p.SoPath = ParamItem{
Key: "queryNode.soPath",
Version: "2.3.0",
DefaultValue: "",
}
p.SoPath.Init(base.mgr)
p.FlowGraphMaxQueueLength = ParamItem{
Key: "queryNode.dataSync.flowGraph.maxQueueLength",
Version: "2.0.0",

View File

@ -8,25 +8,33 @@ import (
const hookYamlFile = "hook.yaml"
type hookConfig struct {
SoPath ParamItem `refreshable:"false"`
SoConfig ParamGroup `refreshable:"false"`
SoPath ParamItem `refreshable:"false"`
SoConfig ParamGroup `refreshable:"false"`
QueryNodePluginConfig ParamItem `refreshable:"true"`
}
func (h *hookConfig) init() {
base := &BaseTable{YamlFiles: []string{hookYamlFile}}
base.init(0)
log.Info("hook config", zap.Any("hook", base.FileConfigs()))
func (h *hookConfig) init(base *BaseTable) {
hookBase := &BaseTable{YamlFiles: []string{hookYamlFile}}
hookBase.init(0)
log.Info("hook config", zap.Any("hook", hookBase.FileConfigs()))
h.SoPath = ParamItem{
Key: "soPath",
Version: "2.0.0",
DefaultValue: "",
}
h.SoPath.Init(base.mgr)
h.SoPath.Init(hookBase.mgr)
h.SoConfig = ParamGroup{
KeyPrefix: "",
Version: "2.2.0",
}
h.SoConfig.Init(base.mgr)
h.SoConfig.Init(hookBase.mgr)
h.QueryNodePluginConfig = ParamItem{
Key: "autoindex.params.search",
Version: "2.3.0",
}
h.QueryNodePluginConfig.Init(base.mgr)
}

View File

@ -106,7 +106,6 @@ go test -race -cover ${APPLE_SILICON_FLAG} "${MILVUS_DIR}/config/..." -failfast
function test_util()
{
go test -race -cover ${APPLE_SILICON_FLAG} "${MILVUS_DIR}/util/autoindex/..." -failfast -count=1
go test -race -cover ${APPLE_SILICON_FLAG} "${MILVUS_DIR}/util/funcutil/..." -failfast -count=1
go test -race -cover ${APPLE_SILICON_FLAG} "${MILVUS_DIR}/util/paramtable/..." -failfast -count=1
go test -race -cover ${APPLE_SILICON_FLAG} "${MILVUS_DIR}/util/retry/..." -failfast -count=1