mirror of
https://gitee.com/milvus-io/milvus.git
synced 2024-12-02 03:48:37 +08:00
Add querynode plugin (#22379)
Signed-off-by: chasingegg <chao.gao@zilliz.com>
This commit is contained in:
parent
ef93e24da7
commit
8b3e5189e1
1
go.mod
1
go.mod
@ -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
3
go.sum
@ -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=
|
||||
|
@ -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 {
|
||||
|
@ -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.
|
||||
|
@ -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()
|
||||
|
@ -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 {
|
||||
|
@ -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{
|
||||
|
@ -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")
|
||||
}
|
||||
)
|
||||
|
@ -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()
|
||||
|
@ -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,
|
||||
|
@ -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,
|
||||
|
@ -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
|
||||
|
@ -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 {
|
||||
|
@ -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{
|
||||
|
@ -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
|
||||
}
|
||||
|
||||
|
@ -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)
|
||||
|
||||
|
@ -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()
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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
|
||||
}
|
@ -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)
|
||||
})
|
||||
}
|
@ -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
|
||||
}
|
@ -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))
|
||||
})
|
||||
}
|
@ -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
|
||||
}
|
@ -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)
|
||||
})
|
||||
}
|
@ -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
|
||||
}
|
@ -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)
|
||||
|
||||
}
|
||||
}
|
@ -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
|
||||
}
|
@ -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)
|
||||
})
|
||||
|
||||
}
|
@ -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
|
||||
}
|
||||
|
@ -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)
|
||||
})
|
||||
}
|
||||
|
@ -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",
|
||||
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
@ -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",
|
||||
|
@ -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)
|
||||
}
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user