mirror of https://github.com/milvus-io/milvus.git
Merging multiple shard query/search requests into one rpc request if QueryNode is the leader of multiple shards of Collection (#17588)
Signed-off-by: Zach41 <zongmei.zhang@zilliz.com>pull/18125/head
parent
b923994b78
commit
1c9647ff31
|
@ -236,7 +236,7 @@ message ReleaseSegmentsRequest {
|
|||
|
||||
message SearchRequest {
|
||||
internal.SearchRequest req = 1;
|
||||
string dml_channel = 2;
|
||||
repeated string dml_channels = 2;
|
||||
repeated int64 segmentIDs = 3;
|
||||
bool from_shard_leader = 4;
|
||||
DataScope scope = 5; // All, Streaming, Historical
|
||||
|
@ -244,7 +244,7 @@ message SearchRequest {
|
|||
|
||||
message QueryRequest {
|
||||
internal.RetrieveRequest req = 1;
|
||||
string dml_channel = 2;
|
||||
repeated string dml_channels = 2;
|
||||
repeated int64 segmentIDs = 3;
|
||||
bool from_shard_leader = 4;
|
||||
DataScope scope = 5; // All, Streaming, Historical
|
||||
|
|
|
@ -1714,7 +1714,7 @@ func (m *ReleaseSegmentsRequest) GetScope() DataScope {
|
|||
|
||||
type SearchRequest struct {
|
||||
Req *internalpb.SearchRequest `protobuf:"bytes,1,opt,name=req,proto3" json:"req,omitempty"`
|
||||
DmlChannel string `protobuf:"bytes,2,opt,name=dml_channel,json=dmlChannel,proto3" json:"dml_channel,omitempty"`
|
||||
DmlChannels []string `protobuf:"bytes,2,rep,name=dml_channels,json=dmlChannels,proto3" json:"dml_channels,omitempty"`
|
||||
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"`
|
||||
|
@ -1755,11 +1755,11 @@ func (m *SearchRequest) GetReq() *internalpb.SearchRequest {
|
|||
return nil
|
||||
}
|
||||
|
||||
func (m *SearchRequest) GetDmlChannel() string {
|
||||
func (m *SearchRequest) GetDmlChannels() []string {
|
||||
if m != nil {
|
||||
return m.DmlChannel
|
||||
return m.DmlChannels
|
||||
}
|
||||
return ""
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *SearchRequest) GetSegmentIDs() []int64 {
|
||||
|
@ -1785,7 +1785,7 @@ func (m *SearchRequest) GetScope() DataScope {
|
|||
|
||||
type QueryRequest struct {
|
||||
Req *internalpb.RetrieveRequest `protobuf:"bytes,1,opt,name=req,proto3" json:"req,omitempty"`
|
||||
DmlChannel string `protobuf:"bytes,2,opt,name=dml_channel,json=dmlChannel,proto3" json:"dml_channel,omitempty"`
|
||||
DmlChannels []string `protobuf:"bytes,2,rep,name=dml_channels,json=dmlChannels,proto3" json:"dml_channels,omitempty"`
|
||||
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"`
|
||||
|
@ -1826,11 +1826,11 @@ func (m *QueryRequest) GetReq() *internalpb.RetrieveRequest {
|
|||
return nil
|
||||
}
|
||||
|
||||
func (m *QueryRequest) GetDmlChannel() string {
|
||||
func (m *QueryRequest) GetDmlChannels() []string {
|
||||
if m != nil {
|
||||
return m.DmlChannel
|
||||
return m.DmlChannels
|
||||
}
|
||||
return ""
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *QueryRequest) GetSegmentIDs() []int64 {
|
||||
|
@ -2804,191 +2804,190 @@ func init() {
|
|||
func init() { proto.RegisterFile("query_coord.proto", fileDescriptor_aab7cc9a69ed26e8) }
|
||||
|
||||
var fileDescriptor_aab7cc9a69ed26e8 = []byte{
|
||||
// 2929 bytes of a gzipped FileDescriptorProto
|
||||
// 2928 bytes of a gzipped FileDescriptorProto
|
||||
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xec, 0x3a, 0xc9, 0x8f, 0x1c, 0x57,
|
||||
0xf9, 0x53, 0xbd, 0x4d, 0xf7, 0xd7, 0x5b, 0xf9, 0x8d, 0x3d, 0xee, 0xf4, 0xcf, 0x4e, 0x9c, 0x72,
|
||||
0x9c, 0xcc, 0x6f, 0x42, 0xc6, 0x66, 0x1c, 0xa2, 0x04, 0x82, 0x84, 0x3d, 0x13, 0x4f, 0x06, 0xdb,
|
||||
0x93, 0xa1, 0xda, 0x0e, 0xc8, 0x8a, 0x54, 0x54, 0x57, 0xbd, 0xe9, 0x29, 0xb9, 0x96, 0x76, 0xbd,
|
||||
0x93, 0xa1, 0xda, 0x0e, 0xc8, 0x8a, 0xd4, 0x54, 0x77, 0xbd, 0xe9, 0x29, 0xb9, 0x96, 0x76, 0xbd,
|
||||
0xea, 0x71, 0x26, 0x67, 0x84, 0xc4, 0x76, 0x40, 0x5c, 0x51, 0xc4, 0x01, 0x0e, 0x48, 0x44, 0x5c,
|
||||
0xb8, 0x20, 0x21, 0xc4, 0x8d, 0x2b, 0x12, 0x7f, 0x00, 0x47, 0x04, 0x77, 0xc4, 0x15, 0xbd, 0xa5,
|
||||
0xf6, 0x2a, 0x77, 0x8f, 0x27, 0x4e, 0x82, 0xc4, 0xad, 0xea, 0x7b, 0xcb, 0xb7, 0x6f, 0xef, 0x3d,
|
||||
0x38, 0xf3, 0x68, 0x86, 0xfd, 0x63, 0xcd, 0xf0, 0x3c, 0xdf, 0xdc, 0x98, 0xfa, 0x5e, 0xe0, 0x21,
|
||||
0xe4, 0x58, 0xf6, 0xd1, 0x8c, 0xf0, 0xbf, 0x0d, 0x36, 0x3e, 0xec, 0x18, 0x9e, 0xe3, 0x78, 0x2e,
|
||||
0x87, 0x0d, 0x3b, 0xc9, 0x19, 0xc3, 0x9e, 0xe5, 0x06, 0xd8, 0x77, 0x75, 0x3b, 0x1c, 0x25, 0xc6,
|
||||
0x21, 0x76, 0x74, 0xf1, 0x27, 0x9b, 0x7a, 0xa0, 0x27, 0xf7, 0x57, 0xbe, 0x27, 0xc1, 0xea, 0xe8,
|
||||
0xd0, 0x7b, 0xbc, 0xe5, 0xd9, 0x36, 0x36, 0x02, 0xcb, 0x73, 0x89, 0x8a, 0x1f, 0xcd, 0x30, 0x09,
|
||||
0xd0, 0x35, 0xa8, 0x8d, 0x75, 0x82, 0x07, 0xd2, 0x25, 0x69, 0xad, 0xbd, 0x79, 0x61, 0x23, 0x45,
|
||||
0x89, 0x20, 0xe1, 0x2e, 0x99, 0xdc, 0xd4, 0x09, 0x56, 0xd9, 0x4c, 0x84, 0xa0, 0x66, 0x8e, 0x77,
|
||||
0xb7, 0x07, 0x95, 0x4b, 0xd2, 0x5a, 0x55, 0x65, 0xdf, 0xe8, 0x25, 0xe8, 0x1a, 0xd1, 0xde, 0xbb,
|
||||
0xdb, 0x64, 0x50, 0xbd, 0x54, 0x5d, 0xab, 0xaa, 0x69, 0xa0, 0xf2, 0x37, 0x09, 0xce, 0xe7, 0xc8,
|
||||
0x20, 0x53, 0xcf, 0x25, 0x18, 0x5d, 0x87, 0x06, 0x09, 0xf4, 0x60, 0x46, 0x04, 0x25, 0xff, 0x57,
|
||||
0x48, 0xc9, 0x88, 0x4d, 0x51, 0xc5, 0xd4, 0x3c, 0xda, 0x4a, 0x01, 0x5a, 0xf4, 0x65, 0x38, 0x6b,
|
||||
0xb9, 0x77, 0xb1, 0xe3, 0xf9, 0xc7, 0xda, 0x14, 0xfb, 0x06, 0x76, 0x03, 0x7d, 0x82, 0x43, 0x1a,
|
||||
0x57, 0xc2, 0xb1, 0xfd, 0x78, 0x08, 0xbd, 0x01, 0xe7, 0xb9, 0x96, 0x08, 0xf6, 0x8f, 0x2c, 0x03,
|
||||
0x6b, 0xfa, 0x91, 0x6e, 0xd9, 0xfa, 0xd8, 0xc6, 0x83, 0xda, 0xa5, 0xea, 0x5a, 0x53, 0x3d, 0xc7,
|
||||
0x86, 0x47, 0x7c, 0xf4, 0x46, 0x38, 0xa8, 0xfc, 0x4a, 0x82, 0x73, 0x94, 0xc3, 0x7d, 0xdd, 0x0f,
|
||||
0xac, 0x67, 0x20, 0x67, 0x05, 0x3a, 0x49, 0xde, 0x06, 0x55, 0x36, 0x96, 0x82, 0xd1, 0x39, 0xd3,
|
||||
0x10, 0x3d, 0x95, 0x49, 0x8d, 0xb1, 0x99, 0x82, 0x29, 0xbf, 0x14, 0x06, 0x91, 0xa4, 0xf3, 0x34,
|
||||
0x8a, 0xc8, 0xe2, 0xac, 0xe4, 0x71, 0x3e, 0x85, 0x1a, 0x94, 0xbf, 0x4b, 0x70, 0xee, 0x8e, 0xa7,
|
||||
0x9b, 0xb1, 0xc1, 0x7c, 0xf6, 0xe2, 0xfc, 0x3a, 0x34, 0xb8, 0x77, 0x0d, 0x6a, 0x0c, 0xd7, 0x95,
|
||||
0x34, 0x2e, 0xe1, 0x79, 0x31, 0x85, 0x23, 0x06, 0x50, 0xc5, 0x22, 0x74, 0x05, 0x7a, 0x3e, 0x9e,
|
||||
0xda, 0x96, 0xa1, 0x6b, 0xee, 0xcc, 0x19, 0x63, 0x7f, 0x50, 0xbf, 0x24, 0xad, 0xd5, 0xd5, 0xae,
|
||||
0x80, 0xee, 0x31, 0xa0, 0xf2, 0x73, 0x09, 0x06, 0x2a, 0xb6, 0xb1, 0x4e, 0xf0, 0xe7, 0xc9, 0xec,
|
||||
0x2a, 0x34, 0x5c, 0xcf, 0xc4, 0xbb, 0xdb, 0x8c, 0xd9, 0xaa, 0x2a, 0xfe, 0x94, 0x1f, 0x55, 0xb8,
|
||||
0x22, 0xbe, 0xe0, 0x76, 0x9d, 0x50, 0x56, 0xfd, 0xd3, 0x51, 0x56, 0xa3, 0x48, 0x59, 0x7f, 0x8a,
|
||||
0x95, 0xf5, 0x45, 0x17, 0x48, 0xac, 0xd0, 0x7a, 0x4a, 0xa1, 0xbf, 0x96, 0xe0, 0xb9, 0x1d, 0x1c,
|
||||
0x44, 0xe4, 0x53, 0x7f, 0xc6, 0x5f, 0xd0, 0x60, 0xf5, 0x89, 0x04, 0xc3, 0x22, 0x5a, 0x4f, 0x13,
|
||||
0xb0, 0x1e, 0xc0, 0x6a, 0x84, 0x43, 0x33, 0x31, 0x31, 0x7c, 0x6b, 0xca, 0xd4, 0xc8, 0x42, 0x57,
|
||||
0x7b, 0xf3, 0xf2, 0x46, 0x3e, 0x25, 0x6f, 0x64, 0x29, 0x38, 0x17, 0x6d, 0xb1, 0x9d, 0xd8, 0x41,
|
||||
0xf9, 0x89, 0x04, 0xe7, 0x76, 0x70, 0x30, 0xc2, 0x13, 0x07, 0xbb, 0xc1, 0xae, 0x7b, 0xe0, 0x3d,
|
||||
0xbd, 0x5c, 0x9f, 0x07, 0x20, 0x62, 0x9f, 0x28, 0xac, 0x26, 0x20, 0x8b, 0xc8, 0x98, 0x65, 0xff,
|
||||
0x2c, 0x3d, 0xa7, 0x91, 0xdd, 0x57, 0xa0, 0x6e, 0xb9, 0x07, 0x5e, 0x28, 0xaa, 0x17, 0x8a, 0x44,
|
||||
0x95, 0x44, 0xc6, 0x67, 0x2b, 0x2e, 0xa7, 0xe2, 0x50, 0xf7, 0xcd, 0x3b, 0x58, 0x37, 0xb1, 0x7f,
|
||||
0x0a, 0x73, 0xcb, 0xb2, 0x5d, 0x29, 0x60, 0xfb, 0xc7, 0x12, 0x9c, 0xcf, 0x21, 0x3c, 0x0d, 0xdf,
|
||||
0x6f, 0x43, 0x83, 0xd0, 0xcd, 0x42, 0xc6, 0x5f, 0x2a, 0x64, 0x3c, 0x81, 0xee, 0x8e, 0x45, 0x02,
|
||||
0x55, 0xac, 0x51, 0x3c, 0x90, 0xb3, 0x63, 0xe8, 0x45, 0xe8, 0x18, 0x87, 0xba, 0xeb, 0x62, 0x5b,
|
||||
0x73, 0x75, 0x87, 0x0b, 0xa0, 0xa5, 0xb6, 0x05, 0x6c, 0x4f, 0x77, 0x30, 0x7a, 0x0e, 0x9a, 0xd4,
|
||||
0x65, 0x35, 0xcb, 0x0c, 0xd5, 0xbf, 0xcc, 0x5c, 0xd8, 0x24, 0xe8, 0x22, 0x00, 0x1b, 0xd2, 0x4d,
|
||||
0xd3, 0xe7, 0x69, 0xb4, 0xa5, 0xb6, 0x28, 0xe4, 0x06, 0x05, 0x28, 0x3f, 0x95, 0xa0, 0x43, 0x63,
|
||||
0xf6, 0x5d, 0x1c, 0xe8, 0x54, 0x0f, 0xe8, 0x2d, 0x68, 0xd9, 0x9e, 0x6e, 0x6a, 0xc1, 0xf1, 0x94,
|
||||
0xa3, 0xea, 0x65, 0x65, 0xcd, 0x59, 0xa0, 0x8b, 0xee, 0x1d, 0x4f, 0xb1, 0xda, 0xb4, 0xc5, 0xd7,
|
||||
0x22, 0xf2, 0xce, 0xb9, 0x72, 0xb5, 0xc0, 0x95, 0xbf, 0x5f, 0x87, 0xd5, 0x6f, 0xeb, 0x81, 0x71,
|
||||
0xb8, 0xed, 0x6c, 0x71, 0x26, 0x4f, 0x61, 0x04, 0x71, 0x6c, 0xab, 0x24, 0x63, 0xdb, 0xa7, 0x16,
|
||||
0x3b, 0x23, 0x3b, 0xaf, 0x17, 0xd9, 0x39, 0x2d, 0xb2, 0x37, 0xde, 0x17, 0xaa, 0x4a, 0xd8, 0x79,
|
||||
0x22, 0x07, 0x35, 0x9e, 0x26, 0x07, 0x6d, 0x41, 0x17, 0x7f, 0x68, 0xd8, 0x33, 0xaa, 0x73, 0x86,
|
||||
0x7d, 0x99, 0x61, 0x7f, 0xbe, 0x00, 0x7b, 0xd2, 0xc9, 0x3a, 0x62, 0xd1, 0xae, 0xa0, 0x81, 0xab,
|
||||
0xda, 0xc1, 0x81, 0x3e, 0x68, 0x32, 0x32, 0x2e, 0x95, 0xa9, 0x3a, 0xb4, 0x0f, 0xae, 0x6e, 0xfa,
|
||||
0x87, 0x2e, 0x40, 0x4b, 0x64, 0xbc, 0xdd, 0xed, 0x41, 0x8b, 0x89, 0x2f, 0x06, 0x20, 0x1d, 0xba,
|
||||
0x22, 0x02, 0x09, 0x0a, 0x81, 0x51, 0xf8, 0x76, 0x11, 0x82, 0x62, 0x65, 0x27, 0x29, 0x27, 0xef,
|
||||
0xb8, 0x81, 0x7f, 0xac, 0x76, 0x48, 0x02, 0x34, 0xd4, 0xe0, 0x4c, 0x6e, 0x0a, 0x92, 0xa1, 0xfa,
|
||||
0x10, 0x1f, 0x33, 0x03, 0xa9, 0xaa, 0xf4, 0x13, 0xbd, 0x0e, 0xf5, 0x23, 0xdd, 0x9e, 0x61, 0x66,
|
||||
0x00, 0xf3, 0x65, 0xc4, 0x27, 0x7f, 0xb5, 0xf2, 0xa6, 0xa4, 0x7c, 0x5c, 0x81, 0xe7, 0x38, 0x6d,
|
||||
0xd8, 0x0e, 0xf4, 0xcf, 0xd7, 0x16, 0x23, 0x3b, 0xab, 0x9d, 0xc8, 0xce, 0x2e, 0x02, 0x84, 0xc5,
|
||||
0x8a, 0x65, 0x8a, 0xf4, 0x1e, 0x69, 0xc9, 0x4c, 0x9b, 0x40, 0xeb, 0xa4, 0x26, 0xa0, 0xfc, 0xb1,
|
||||
0x06, 0x7d, 0x21, 0x3b, 0x3a, 0x83, 0x05, 0x90, 0x0b, 0xd0, 0x8a, 0x52, 0x8f, 0x50, 0x43, 0x0c,
|
||||
0x40, 0x97, 0xa0, 0x9d, 0x70, 0x1f, 0x21, 0x87, 0x24, 0x68, 0x21, 0x61, 0x84, 0x85, 0x44, 0x2d,
|
||||
0x51, 0x48, 0x5c, 0x04, 0x38, 0xb0, 0x67, 0xe4, 0x50, 0x0b, 0x2c, 0x07, 0x87, 0x9c, 0x32, 0xc8,
|
||||
0x3d, 0xcb, 0xc1, 0xe8, 0x06, 0x74, 0xc6, 0x96, 0x6b, 0x7b, 0x13, 0x6d, 0xaa, 0x07, 0x87, 0x64,
|
||||
0xd0, 0x28, 0x75, 0x98, 0x5b, 0x16, 0xb6, 0xcd, 0x9b, 0x6c, 0xae, 0xda, 0xe6, 0x6b, 0xf6, 0xe9,
|
||||
0x12, 0xf4, 0x3c, 0xb4, 0xdd, 0x99, 0xa3, 0x79, 0x07, 0x9a, 0xef, 0x3d, 0xa6, 0x2e, 0xc7, 0x50,
|
||||
0xb8, 0x33, 0xe7, 0xbd, 0x03, 0xd5, 0x7b, 0x4c, 0x43, 0x7f, 0x8b, 0x26, 0x01, 0x62, 0x7b, 0x13,
|
||||
0x32, 0x68, 0x2e, 0xb4, 0x7f, 0xbc, 0x80, 0xae, 0x36, 0xa9, 0x99, 0xb1, 0xd5, 0xad, 0xc5, 0x56,
|
||||
0x47, 0x0b, 0xd0, 0xcb, 0xd0, 0x33, 0x3c, 0x67, 0xaa, 0x33, 0x09, 0xdd, 0xf2, 0x3d, 0x87, 0xf9,
|
||||
0x5b, 0x55, 0xcd, 0x40, 0xd1, 0x16, 0xb4, 0x2d, 0xd7, 0xc4, 0x1f, 0x0a, 0xa7, 0x6c, 0x33, 0x3c,
|
||||
0x4a, 0x91, 0xca, 0x19, 0xa2, 0x5d, 0x3a, 0x97, 0x29, 0x1d, 0xac, 0xf0, 0x93, 0xd0, 0x8c, 0x14,
|
||||
0xfa, 0x36, 0xb1, 0x3e, 0xc2, 0x83, 0x0e, 0xd7, 0xa2, 0x80, 0x8d, 0xac, 0x8f, 0x30, 0x2d, 0x92,
|
||||
0x2d, 0x97, 0x60, 0x3f, 0xd0, 0x84, 0x51, 0x0e, 0xba, 0x2c, 0x6d, 0x75, 0x39, 0x54, 0xf8, 0x92,
|
||||
0xf2, 0xdb, 0x0a, 0xf4, 0xd2, 0x88, 0xd0, 0x00, 0x96, 0x0f, 0x18, 0x24, 0xb4, 0x9e, 0xf0, 0x97,
|
||||
0xa2, 0xc5, 0x2e, 0xed, 0xa0, 0x35, 0x46, 0x0b, 0x33, 0x9e, 0xa6, 0xda, 0xe6, 0x30, 0xb6, 0x01,
|
||||
0x35, 0x02, 0xce, 0x1e, 0xcb, 0x94, 0x55, 0x86, 0xb2, 0xc5, 0x20, 0x2c, 0x4f, 0x0e, 0x60, 0x99,
|
||||
0xb3, 0x11, 0x9a, 0x4e, 0xf8, 0x4b, 0x47, 0xc6, 0x33, 0x8b, 0x61, 0xe5, 0xa6, 0x13, 0xfe, 0xa2,
|
||||
0x6d, 0xe8, 0xf0, 0x2d, 0xa7, 0xba, 0xaf, 0x3b, 0xa1, 0xe1, 0xbc, 0x58, 0xe8, 0xee, 0xb7, 0xf1,
|
||||
0xf1, 0xfb, 0x34, 0x7a, 0xec, 0xeb, 0x96, 0xaf, 0x72, 0x41, 0xef, 0xb3, 0x55, 0x68, 0x0d, 0x64,
|
||||
0xbe, 0xcb, 0x81, 0x65, 0x63, 0x61, 0x82, 0xcb, 0x2c, 0x19, 0xf7, 0x18, 0xfc, 0x96, 0x65, 0x63,
|
||||
0x6e, 0x65, 0x11, 0x0b, 0x4c, 0xb4, 0x4d, 0x6e, 0x64, 0x0c, 0x42, 0x05, 0xab, 0xfc, 0xb5, 0x0a,
|
||||
0x2b, 0xd4, 0xd7, 0x84, 0xdb, 0x9d, 0x22, 0x1a, 0x5d, 0x04, 0x30, 0x49, 0xa0, 0xa5, 0x22, 0x52,
|
||||
0xcb, 0x24, 0xc1, 0x1e, 0x0f, 0x4a, 0x6f, 0x85, 0x01, 0xa7, 0x5a, 0x5e, 0xeb, 0x66, 0x7c, 0x3f,
|
||||
0x9f, 0xdc, 0x9e, 0xaa, 0x1b, 0xbe, 0x0c, 0x5d, 0xe2, 0xcd, 0x7c, 0x03, 0x6b, 0xa9, 0xae, 0xa4,
|
||||
0xc3, 0x81, 0x7b, 0xc5, 0x31, 0xb3, 0x51, 0xd8, 0x95, 0x27, 0xa2, 0xdb, 0xf2, 0xe9, 0x12, 0x5c,
|
||||
0x33, 0x9b, 0xe0, 0x6e, 0x43, 0x9f, 0xb9, 0x9f, 0x36, 0xf5, 0x08, 0x6f, 0xee, 0x84, 0xd7, 0x66,
|
||||
0xbc, 0x29, 0x3a, 0x85, 0xbb, 0x4b, 0x26, 0xfb, 0x62, 0xaa, 0xda, 0x63, 0x4b, 0xc3, 0x5f, 0xa2,
|
||||
0xfc, 0xac, 0x02, 0xab, 0xa2, 0x59, 0x3c, 0xbd, 0x62, 0xcb, 0xd2, 0x4c, 0x18, 0x35, 0xab, 0x4f,
|
||||
0x68, 0xbf, 0x6a, 0x0b, 0x94, 0x41, 0xf5, 0x82, 0x32, 0x28, 0xdd, 0x82, 0x34, 0x72, 0x2d, 0xc8,
|
||||
0x75, 0xa8, 0x13, 0xc3, 0x9b, 0x62, 0xa6, 0x86, 0xde, 0xe6, 0xc5, 0x22, 0x35, 0x6c, 0xeb, 0x81,
|
||||
0x3e, 0xa2, 0x93, 0x54, 0x3e, 0x57, 0xf9, 0x87, 0x04, 0xdd, 0x11, 0xd6, 0x7d, 0xe3, 0x30, 0x14,
|
||||
0xc6, 0x1b, 0x50, 0xf5, 0xf1, 0x23, 0x21, 0x8b, 0x97, 0x4a, 0x04, 0x9d, 0x5a, 0xa2, 0xd2, 0x05,
|
||||
0xe8, 0x05, 0x68, 0x9b, 0x8e, 0x1d, 0xc5, 0xa2, 0x0a, 0x0b, 0x0c, 0x60, 0x3a, 0xb6, 0x08, 0x44,
|
||||
0x19, 0xfa, 0xab, 0x39, 0xfa, 0xd7, 0xe1, 0xcc, 0x81, 0xef, 0x39, 0x1a, 0xab, 0xd3, 0x35, 0x9b,
|
||||
0x95, 0xe7, 0x4c, 0x58, 0x4d, 0xb5, 0x4f, 0x07, 0x12, 0x55, 0x7b, 0xcc, 0x6b, 0xfd, 0x04, 0xbc,
|
||||
0xfe, 0x53, 0x82, 0xce, 0xb7, 0xe8, 0x50, 0xc8, 0xea, 0x9b, 0x49, 0x56, 0x5f, 0x2e, 0x61, 0x55,
|
||||
0xc5, 0x81, 0x6f, 0xe1, 0x23, 0xfc, 0x5f, 0xc6, 0xec, 0x9f, 0x25, 0x18, 0x8e, 0x8e, 0x5d, 0x43,
|
||||
0xe5, 0xde, 0x74, 0x7a, 0x93, 0xbf, 0x0c, 0xdd, 0xa3, 0x54, 0x93, 0xc4, 0x99, 0xee, 0x1c, 0x25,
|
||||
0xbb, 0x24, 0x15, 0xe4, 0xb0, 0x16, 0x12, 0xcc, 0x86, 0xc1, 0xed, 0x95, 0x22, 0xaa, 0x33, 0xc4,
|
||||
0xb1, 0xe0, 0xd0, 0xf7, 0xd3, 0x40, 0xc5, 0x87, 0x95, 0x82, 0x79, 0xe8, 0x3c, 0x2c, 0x8b, 0x86,
|
||||
0x4c, 0x24, 0x31, 0xee, 0x83, 0x26, 0xcd, 0x61, 0xf1, 0x91, 0x82, 0x65, 0xe6, 0x0b, 0x20, 0x93,
|
||||
0xaa, 0x2f, 0xaa, 0x9c, 0xcd, 0x9c, 0x7a, 0x4c, 0xa2, 0xfc, 0x41, 0x82, 0xd5, 0x77, 0x75, 0xd7,
|
||||
0xf4, 0x0e, 0x0e, 0x4e, 0x2f, 0xb9, 0x2d, 0x48, 0x15, 0xd5, 0x8b, 0xb6, 0xeb, 0xa9, 0x45, 0xe8,
|
||||
0x55, 0x38, 0xe3, 0xf3, 0xe8, 0x65, 0xa6, 0x45, 0x5b, 0x55, 0xe5, 0x70, 0x20, 0x12, 0xd9, 0x6f,
|
||||
0x2a, 0x80, 0x68, 0xc4, 0xbd, 0xa9, 0xdb, 0xba, 0x6b, 0xe0, 0xa7, 0x27, 0xfd, 0x0a, 0xf4, 0x52,
|
||||
0x79, 0x22, 0x3a, 0xd9, 0x4f, 0x26, 0x0a, 0x82, 0x6e, 0x43, 0x6f, 0xcc, 0x51, 0x69, 0x3e, 0xd6,
|
||||
0x89, 0xe7, 0xb2, 0x00, 0xd8, 0x2b, 0xee, 0xcc, 0xef, 0xf9, 0xd6, 0x64, 0x82, 0xfd, 0x2d, 0xcf,
|
||||
0x35, 0x79, 0xa4, 0xee, 0x8e, 0x43, 0x32, 0xe9, 0x52, 0xe6, 0x5b, 0x51, 0xd2, 0x0c, 0x3b, 0x42,
|
||||
0x88, 0xb2, 0x26, 0x13, 0x05, 0xc1, 0xba, 0x1d, 0x0b, 0x22, 0x8e, 0x98, 0x32, 0x1f, 0x18, 0x95,
|
||||
0x1f, 0xcc, 0x14, 0x24, 0x31, 0xe5, 0x77, 0x12, 0xa0, 0xa8, 0x37, 0x62, 0xdd, 0x08, 0xb3, 0xb0,
|
||||
0xec, 0x52, 0xa9, 0x20, 0x70, 0x5f, 0x80, 0x96, 0x19, 0xae, 0x14, 0x1e, 0x11, 0x03, 0xa8, 0xcf,
|
||||
0x70, 0x36, 0x34, 0x9a, 0xf1, 0xb0, 0x19, 0x56, 0xda, 0x1c, 0x78, 0x87, 0xc1, 0xd2, 0x39, 0xb0,
|
||||
0x96, 0xcd, 0x81, 0xc9, 0x73, 0x87, 0x7a, 0xea, 0xdc, 0x41, 0xf9, 0xa4, 0x02, 0x32, 0x8b, 0x67,
|
||||
0x5b, 0x71, 0x53, 0xb2, 0x10, 0xd1, 0x97, 0xa1, 0x2b, 0xee, 0xbe, 0x52, 0x84, 0x77, 0x1e, 0x25,
|
||||
0x36, 0x43, 0xd7, 0xe0, 0x2c, 0x9f, 0xe4, 0x63, 0x32, 0xb3, 0xe3, 0x22, 0x93, 0x57, 0x7c, 0xe8,
|
||||
0x11, 0x0f, 0xa4, 0x74, 0x28, 0x5c, 0x71, 0x1f, 0x56, 0x27, 0xb6, 0x37, 0xd6, 0x6d, 0x2d, 0xad,
|
||||
0x9e, 0x92, 0x86, 0x2a, 0x6f, 0xf1, 0x67, 0xf9, 0xf2, 0x51, 0x52, 0x87, 0x04, 0xed, 0xd0, 0x36,
|
||||
0x17, 0x3f, 0x8c, 0x8a, 0x00, 0x71, 0xa4, 0xbc, 0x48, 0x0d, 0xd0, 0xa1, 0x0b, 0xc3, 0x3f, 0xe5,
|
||||
0x63, 0x09, 0xfa, 0x99, 0xa3, 0xc3, 0x6c, 0xb3, 0x24, 0xe5, 0x9b, 0xa5, 0x37, 0xa1, 0x4e, 0x3b,
|
||||
0x08, 0x1e, 0xef, 0x7a, 0xc5, 0x85, 0x7c, 0x7a, 0x57, 0x95, 0x2f, 0x40, 0x57, 0x61, 0xa5, 0xe0,
|
||||
0xa2, 0x45, 0xd8, 0x00, 0xca, 0xdf, 0xb3, 0x28, 0xbf, 0xaf, 0x41, 0x3b, 0x21, 0x8f, 0x39, 0x7d,
|
||||
0xde, 0x22, 0x67, 0x41, 0x19, 0xf6, 0xaa, 0x79, 0xf6, 0x4a, 0x6e, 0x1a, 0xa8, 0xdd, 0x39, 0xd8,
|
||||
0xe1, 0x15, 0xb2, 0x28, 0xd7, 0x1d, 0xec, 0xb0, 0xc6, 0x83, 0x9a, 0xe4, 0xcc, 0xe1, 0x1d, 0x1a,
|
||||
0x77, 0xa7, 0x65, 0x77, 0xe6, 0xb0, 0xfe, 0x2c, 0xdd, 0x1c, 0x2c, 0x3f, 0xa1, 0x39, 0x68, 0xa6,
|
||||
0x9b, 0x83, 0x94, 0x1f, 0xb5, 0xb2, 0x7e, 0xb4, 0x68, 0xeb, 0x75, 0x0d, 0x56, 0x0c, 0x1f, 0xeb,
|
||||
0x01, 0x36, 0x6f, 0x1e, 0x6f, 0x45, 0x43, 0x83, 0x36, 0xcb, 0xab, 0x45, 0x43, 0xe8, 0x56, 0x7c,
|
||||
0x86, 0xc2, 0xb5, 0xdc, 0x61, 0x5a, 0x2e, 0xee, 0x3d, 0x84, 0x6e, 0xb8, 0x92, 0xc3, 0xf0, 0xcc,
|
||||
0xfe, 0xb2, 0x4d, 0x5f, 0xf7, 0xa9, 0x9a, 0xbe, 0x17, 0xa0, 0x1d, 0x9f, 0x24, 0x90, 0x41, 0x8f,
|
||||
0x47, 0xbe, 0xe8, 0x28, 0x81, 0xa4, 0x82, 0x41, 0x3f, 0x1d, 0x0c, 0xfe, 0x52, 0x85, 0x5e, 0x5c,
|
||||
0xee, 0x2f, 0x1c, 0x0a, 0x16, 0xb9, 0x30, 0xdc, 0x03, 0x39, 0x4e, 0xa8, 0x4c, 0x4a, 0x4f, 0xec,
|
||||
0x58, 0xb2, 0xa7, 0xf3, 0xfd, 0x69, 0xc6, 0xe7, 0x52, 0xe7, 0x9f, 0xb5, 0x13, 0x9d, 0x7f, 0x9e,
|
||||
0xf2, 0x5e, 0xe9, 0x3a, 0x9c, 0x8b, 0x92, 0x68, 0x8a, 0x6d, 0x5e, 0x4d, 0x9f, 0x0d, 0x07, 0xf7,
|
||||
0x93, 0xec, 0x97, 0xb8, 0xf1, 0x72, 0x99, 0x1b, 0x67, 0xd5, 0xd8, 0xcc, 0xa9, 0x31, 0x7f, 0xbd,
|
||||
0xd5, 0x2a, 0xba, 0xde, 0xba, 0x0f, 0x2b, 0xf7, 0x5d, 0x32, 0x1b, 0x13, 0xc3, 0xb7, 0xc6, 0x38,
|
||||
0x3c, 0x1b, 0x5b, 0x48, 0xad, 0x43, 0x68, 0x8a, 0x78, 0xcd, 0x55, 0xda, 0x52, 0xa3, 0x7f, 0xe5,
|
||||
0x87, 0x12, 0xac, 0xe6, 0xf7, 0x65, 0x16, 0x13, 0x07, 0x03, 0x29, 0x15, 0x0c, 0xbe, 0x03, 0x2b,
|
||||
0xf1, 0xf6, 0x5a, 0x6a, 0xe7, 0x92, 0xca, 0xae, 0x80, 0x70, 0x15, 0xc5, 0x7b, 0x84, 0x30, 0xe5,
|
||||
0x5f, 0x52, 0x74, 0xc2, 0x48, 0x61, 0x13, 0x76, 0x6e, 0x4a, 0x13, 0x94, 0xe7, 0xda, 0x96, 0x1b,
|
||||
0xb5, 0xa7, 0x82, 0x47, 0x0e, 0x14, 0xed, 0xe9, 0xbb, 0xd0, 0x17, 0x93, 0xa2, 0x3c, 0xb3, 0x60,
|
||||
0x65, 0xd5, 0xe3, 0xeb, 0xa2, 0x0c, 0x73, 0x05, 0x7a, 0xde, 0xc1, 0x41, 0x12, 0x1f, 0x0f, 0x94,
|
||||
0x5d, 0x01, 0x15, 0x08, 0xbf, 0x09, 0x72, 0x38, 0xed, 0xa4, 0x99, 0xad, 0x2f, 0x16, 0x46, 0x15,
|
||||
0xda, 0x0f, 0x24, 0x18, 0xa4, 0xf3, 0x5c, 0x82, 0xfd, 0x93, 0xd7, 0x69, 0x5f, 0x4b, 0x5f, 0x05,
|
||||
0x5d, 0x79, 0x02, 0x3d, 0x31, 0x1e, 0x71, 0x96, 0xb0, 0xfe, 0x0d, 0x68, 0x45, 0xed, 0x03, 0x6a,
|
||||
0xc3, 0xf2, 0x7d, 0xf7, 0xb6, 0xeb, 0x3d, 0x76, 0xe5, 0x25, 0xb4, 0x0c, 0xd5, 0x1b, 0xb6, 0x2d,
|
||||
0x4b, 0xa8, 0x0b, 0xad, 0x51, 0xe0, 0x63, 0xdd, 0xb1, 0xdc, 0x89, 0x5c, 0x41, 0x3d, 0x80, 0x77,
|
||||
0x2d, 0x12, 0x78, 0xbe, 0x65, 0xe8, 0xb6, 0x5c, 0x5d, 0xff, 0x08, 0x7a, 0x69, 0xaf, 0x47, 0x1d,
|
||||
0x68, 0xee, 0x79, 0xc1, 0x3b, 0x1f, 0x5a, 0x24, 0x90, 0x97, 0xe8, 0xfc, 0x3d, 0x2f, 0xd8, 0xf7,
|
||||
0x31, 0xc1, 0x6e, 0x20, 0x4b, 0x08, 0xa0, 0xf1, 0x9e, 0xbb, 0x6d, 0x91, 0x87, 0x72, 0x05, 0xad,
|
||||
0x88, 0xa4, 0xac, 0xdb, 0xbb, 0xc2, 0x95, 0xe4, 0x2a, 0x5d, 0x1e, 0xfd, 0xd5, 0x90, 0x0c, 0x9d,
|
||||
0x68, 0xca, 0xce, 0xfe, 0x7d, 0xb9, 0x8e, 0x5a, 0x50, 0xe7, 0x9f, 0x8d, 0x75, 0x13, 0xe4, 0x6c,
|
||||
0x45, 0x49, 0xf7, 0xe4, 0x4c, 0x44, 0x20, 0x79, 0x89, 0x72, 0x26, 0x4a, 0x7a, 0x59, 0x42, 0x7d,
|
||||
0x68, 0x27, 0x0a, 0x64, 0xb9, 0x42, 0x01, 0x3b, 0xfe, 0xd4, 0x10, 0xa5, 0x32, 0x27, 0x81, 0xea,
|
||||
0x7d, 0x9b, 0x4a, 0xa2, 0xb6, 0x7e, 0x13, 0x9a, 0x61, 0x38, 0xa2, 0x53, 0x85, 0x88, 0xe8, 0xaf,
|
||||
0xbc, 0x84, 0xce, 0x40, 0x37, 0x75, 0x29, 0x2f, 0x4b, 0x08, 0x41, 0x2f, 0xfd, 0x60, 0x42, 0xae,
|
||||
0x6c, 0xfe, 0xa2, 0x03, 0xc0, 0xeb, 0x35, 0xcf, 0xf3, 0x4d, 0x34, 0x05, 0xb4, 0x83, 0x03, 0x9a,
|
||||
0x8b, 0x3c, 0x37, 0xcc, 0x23, 0x04, 0x5d, 0x2b, 0x29, 0x6b, 0xf2, 0x53, 0x05, 0xa9, 0xc3, 0xb2,
|
||||
0xc6, 0x35, 0x33, 0x5d, 0x59, 0x42, 0x0e, 0xc3, 0x78, 0xcf, 0x72, 0xf0, 0x3d, 0xcb, 0x78, 0x18,
|
||||
0x15, 0x7a, 0xe5, 0x18, 0x33, 0x53, 0x43, 0x8c, 0x99, 0xb0, 0x2f, 0x7e, 0x46, 0x81, 0x6f, 0xb9,
|
||||
0x93, 0xf0, 0x6a, 0x4f, 0x59, 0x42, 0x8f, 0xe0, 0xec, 0x0e, 0x66, 0xd8, 0x2d, 0x12, 0x58, 0x06,
|
||||
0x09, 0x11, 0x6e, 0x96, 0x23, 0xcc, 0x4d, 0x3e, 0x21, 0x4a, 0x1b, 0xfa, 0x99, 0x87, 0x4d, 0x68,
|
||||
0xbd, 0xf8, 0x76, 0xb0, 0xe8, 0x11, 0xd6, 0xf0, 0xd5, 0x85, 0xe6, 0x46, 0xd8, 0x2c, 0xe8, 0xa5,
|
||||
0x1f, 0xef, 0xa0, 0xff, 0x2f, 0xdb, 0x20, 0xf7, 0x3e, 0x61, 0xb8, 0xbe, 0xc8, 0xd4, 0x08, 0xd5,
|
||||
0x03, 0x6e, 0x4f, 0xf3, 0x50, 0x15, 0xbe, 0x0d, 0x19, 0x3e, 0xe9, 0x56, 0x55, 0x59, 0x42, 0xdf,
|
||||
0x85, 0x33, 0xb9, 0x57, 0x14, 0xe8, 0x4b, 0xc5, 0xfd, 0x7a, 0xf1, 0x63, 0x8b, 0x79, 0x18, 0x1e,
|
||||
0x64, 0xbd, 0xa1, 0x9c, 0xfa, 0xdc, 0xab, 0x9b, 0xc5, 0xa9, 0x4f, 0x6c, 0xff, 0x24, 0xea, 0x4f,
|
||||
0x8c, 0x61, 0xc6, 0xdc, 0x26, 0xdb, 0x39, 0xbc, 0x56, 0x84, 0xa2, 0xf4, 0x29, 0xc7, 0x70, 0x63,
|
||||
0xd1, 0xe9, 0x49, 0xeb, 0x4a, 0xbf, 0x16, 0x28, 0x16, 0x5a, 0xe1, 0x0b, 0x87, 0x62, 0xeb, 0x2a,
|
||||
0x7e, 0x7c, 0xa0, 0x2c, 0xa1, 0x7b, 0xa9, 0x68, 0x88, 0x5e, 0x2e, 0x53, 0x4e, 0xfa, 0x3c, 0x61,
|
||||
0x9e, 0xdc, 0x34, 0x80, 0x1d, 0x1c, 0xdc, 0xc5, 0x81, 0x6f, 0x19, 0x24, 0xbb, 0xa9, 0xf8, 0x89,
|
||||
0x27, 0x84, 0x9b, 0xbe, 0x32, 0x77, 0x5e, 0x44, 0xf6, 0x18, 0xda, 0x3b, 0x38, 0x10, 0x87, 0x43,
|
||||
0x04, 0x95, 0xae, 0x0c, 0x67, 0x84, 0x28, 0xd6, 0xe6, 0x4f, 0x4c, 0x46, 0x94, 0xcc, 0xe3, 0x05,
|
||||
0x54, 0x2a, 0xdb, 0xfc, 0x93, 0x8a, 0xe2, 0x88, 0x52, 0xf2, 0x1a, 0x42, 0x59, 0xda, 0xfc, 0x37,
|
||||
0x40, 0x8b, 0xa5, 0x08, 0x9a, 0x7a, 0xfe, 0x97, 0x21, 0x9e, 0x41, 0x86, 0xf8, 0x00, 0xfa, 0x99,
|
||||
0xbb, 0xf0, 0x62, 0x7d, 0x16, 0x5f, 0x98, 0xcf, 0x33, 0xf9, 0x31, 0xa0, 0xfc, 0x6d, 0x76, 0x71,
|
||||
0xa8, 0x28, 0xbd, 0xf5, 0x9e, 0x87, 0xe3, 0x7d, 0xfe, 0x9c, 0x24, 0xaa, 0x5e, 0x5f, 0x29, 0xf3,
|
||||
0xd6, 0xcc, 0xc9, 0xe5, 0xe7, 0x1f, 0x48, 0x9f, 0x7d, 0xa2, 0xf9, 0x00, 0xfa, 0x99, 0x3b, 0x9e,
|
||||
0x62, 0xed, 0x16, 0x5f, 0x04, 0xcd, 0xdb, 0xfd, 0x33, 0x8c, 0xc8, 0x26, 0xac, 0x14, 0x9c, 0xde,
|
||||
0xa3, 0xc2, 0x2c, 0x52, 0x7e, 0xcc, 0x3f, 0x8f, 0xa1, 0x11, 0x34, 0xf8, 0x4d, 0x0e, 0x7a, 0xb1,
|
||||
0xb8, 0x63, 0x48, 0xdc, 0xf2, 0x0c, 0xe7, 0xdd, 0x05, 0x91, 0x99, 0x1d, 0xf0, 0x4d, 0xeb, 0x2c,
|
||||
0x84, 0xa1, 0xc2, 0x8b, 0xc0, 0xe4, 0x05, 0xcc, 0x70, 0xfe, 0x9d, 0x4b, 0xb8, 0xe9, 0xb3, 0xce,
|
||||
0x25, 0x37, 0x5f, 0x7f, 0xb0, 0x39, 0xb1, 0x82, 0xc3, 0xd9, 0x98, 0x0a, 0xe9, 0x2a, 0x9f, 0xf9,
|
||||
0x9a, 0xe5, 0x89, 0xaf, 0xab, 0x21, 0x69, 0x57, 0xd9, 0x4e, 0x57, 0x19, 0x2f, 0xd3, 0xf1, 0xb8,
|
||||
0xc1, 0x7e, 0xaf, 0xff, 0x27, 0x00, 0x00, 0xff, 0xff, 0x98, 0x70, 0x46, 0x0e, 0x4c, 0x30, 0x00,
|
||||
0x00,
|
||||
0xb8, 0x20, 0x21, 0xc4, 0x8d, 0x2b, 0x12, 0x7f, 0x00, 0x47, 0x0e, 0x70, 0x45, 0x5c, 0xd1, 0xdb,
|
||||
0x6a, 0x2f, 0x77, 0x8f, 0x27, 0x4e, 0x82, 0xc4, 0xad, 0xea, 0x7b, 0xcb, 0xb7, 0x6f, 0xef, 0x3d,
|
||||
0x38, 0xf3, 0x68, 0x86, 0xfd, 0xe3, 0xe1, 0xd8, 0xf3, 0x7c, 0x73, 0x63, 0xea, 0x7b, 0x81, 0x87,
|
||||
0x90, 0x63, 0xd9, 0x47, 0x33, 0xc2, 0xff, 0x36, 0xd8, 0x78, 0xbf, 0x35, 0xf6, 0x1c, 0xc7, 0x73,
|
||||
0x39, 0xac, 0xdf, 0x8a, 0xcf, 0xe8, 0x77, 0x2c, 0x37, 0xc0, 0xbe, 0x6b, 0xd8, 0x72, 0x94, 0x8c,
|
||||
0x0f, 0xb1, 0x63, 0x88, 0x3f, 0xd5, 0x34, 0x02, 0x23, 0xbe, 0xbf, 0xf6, 0x3d, 0x05, 0x56, 0x07,
|
||||
0x87, 0xde, 0xe3, 0x2d, 0xcf, 0xb6, 0xf1, 0x38, 0xb0, 0x3c, 0x97, 0xe8, 0xf8, 0xd1, 0x0c, 0x93,
|
||||
0x00, 0x5d, 0x83, 0xca, 0xc8, 0x20, 0xb8, 0xa7, 0x5c, 0x52, 0xd6, 0x9a, 0x9b, 0x17, 0x36, 0x12,
|
||||
0x94, 0x08, 0x12, 0xee, 0x92, 0xc9, 0x4d, 0x83, 0x60, 0x9d, 0xcd, 0x44, 0x08, 0x2a, 0xe6, 0x68,
|
||||
0x77, 0xbb, 0x57, 0xba, 0xa4, 0xac, 0x95, 0x75, 0xf6, 0x8d, 0x5e, 0x82, 0xf6, 0x38, 0xdc, 0x7b,
|
||||
0x77, 0x9b, 0xf4, 0xca, 0x97, 0xca, 0x6b, 0x65, 0x3d, 0x09, 0xd4, 0xfe, 0xa6, 0xc0, 0xf9, 0x0c,
|
||||
0x19, 0x64, 0xea, 0xb9, 0x04, 0xa3, 0xeb, 0x50, 0x23, 0x81, 0x11, 0xcc, 0x88, 0xa0, 0xe4, 0xff,
|
||||
0x72, 0x29, 0x19, 0xb0, 0x29, 0xba, 0x98, 0x9a, 0x45, 0x5b, 0xca, 0x41, 0x8b, 0xbe, 0x0c, 0x67,
|
||||
0x2d, 0xf7, 0x2e, 0x76, 0x3c, 0xff, 0x78, 0x38, 0xc5, 0xfe, 0x18, 0xbb, 0x81, 0x31, 0xc1, 0x92,
|
||||
0xc6, 0x15, 0x39, 0xb6, 0x1f, 0x0d, 0xa1, 0x37, 0xe0, 0x3c, 0xd7, 0x12, 0xc1, 0xfe, 0x91, 0x35,
|
||||
0xc6, 0x43, 0xe3, 0xc8, 0xb0, 0x6c, 0x63, 0x64, 0xe3, 0x5e, 0xe5, 0x52, 0x79, 0xad, 0xae, 0x9f,
|
||||
0x63, 0xc3, 0x03, 0x3e, 0x7a, 0x43, 0x0e, 0x6a, 0xbf, 0x52, 0xe0, 0x1c, 0xe5, 0x70, 0xdf, 0xf0,
|
||||
0x03, 0xeb, 0x19, 0xc8, 0x59, 0x83, 0x56, 0x9c, 0xb7, 0x5e, 0x99, 0x8d, 0x25, 0x60, 0x74, 0xce,
|
||||
0x54, 0xa2, 0xa7, 0x32, 0xa9, 0x30, 0x36, 0x13, 0x30, 0xed, 0x97, 0xc2, 0x20, 0xe2, 0x74, 0x9e,
|
||||
0x46, 0x11, 0x69, 0x9c, 0xa5, 0x2c, 0xce, 0xa7, 0x50, 0x83, 0xf6, 0x77, 0x05, 0xce, 0xdd, 0xf1,
|
||||
0x0c, 0x33, 0x32, 0x98, 0xcf, 0x5e, 0x9c, 0x5f, 0x87, 0x1a, 0xf7, 0xae, 0x5e, 0x85, 0xe1, 0xba,
|
||||
0x92, 0xc4, 0x25, 0x3c, 0x2f, 0xa2, 0x70, 0xc0, 0x00, 0xba, 0x58, 0x84, 0xae, 0x40, 0xc7, 0xc7,
|
||||
0x53, 0xdb, 0x1a, 0x1b, 0x43, 0x77, 0xe6, 0x8c, 0xb0, 0xdf, 0xab, 0x5e, 0x52, 0xd6, 0xaa, 0x7a,
|
||||
0x5b, 0x40, 0xf7, 0x18, 0x50, 0xfb, 0xb9, 0x02, 0x3d, 0x1d, 0xdb, 0xd8, 0x20, 0xf8, 0xf3, 0x64,
|
||||
0x76, 0x15, 0x6a, 0xae, 0x67, 0xe2, 0xdd, 0x6d, 0xc6, 0x6c, 0x59, 0x17, 0x7f, 0xda, 0x8f, 0x4a,
|
||||
0x5c, 0x11, 0x5f, 0x70, 0xbb, 0x8e, 0x29, 0xab, 0xfa, 0xe9, 0x28, 0xab, 0x96, 0xa7, 0xac, 0x3f,
|
||||
0x45, 0xca, 0xfa, 0xa2, 0x0b, 0x24, 0x52, 0x68, 0x35, 0xa1, 0xd0, 0x5f, 0x2b, 0xf0, 0xdc, 0x0e,
|
||||
0x0e, 0x42, 0xf2, 0xa9, 0x3f, 0xe3, 0x2f, 0x68, 0xb0, 0xfa, 0x44, 0x81, 0x7e, 0x1e, 0xad, 0xa7,
|
||||
0x09, 0x58, 0x0f, 0x60, 0x35, 0xc4, 0x31, 0x34, 0x31, 0x19, 0xfb, 0xd6, 0x94, 0xa9, 0x91, 0x85,
|
||||
0xae, 0xe6, 0xe6, 0xe5, 0x8d, 0x6c, 0x4a, 0xde, 0x48, 0x53, 0x70, 0x2e, 0xdc, 0x62, 0x3b, 0xb6,
|
||||
0x83, 0xf6, 0x13, 0x05, 0xce, 0xed, 0xe0, 0x60, 0x80, 0x27, 0x0e, 0x76, 0x83, 0x5d, 0xf7, 0xc0,
|
||||
0x7b, 0x7a, 0xb9, 0x3e, 0x0f, 0x40, 0xc4, 0x3e, 0x61, 0x58, 0x8d, 0x41, 0x16, 0x91, 0x31, 0xcb,
|
||||
0xfe, 0x69, 0x7a, 0x4e, 0x23, 0xbb, 0xaf, 0x40, 0xd5, 0x72, 0x0f, 0x3c, 0x29, 0xaa, 0x17, 0xf2,
|
||||
0x44, 0x15, 0x47, 0xc6, 0x67, 0x6b, 0x2e, 0xa7, 0xe2, 0xd0, 0xf0, 0xcd, 0x3b, 0xd8, 0x30, 0xb1,
|
||||
0x7f, 0x0a, 0x73, 0x4b, 0xb3, 0x5d, 0xca, 0x61, 0xfb, 0xc7, 0x0a, 0x9c, 0xcf, 0x20, 0x3c, 0x0d,
|
||||
0xdf, 0x6f, 0x43, 0x8d, 0xd0, 0xcd, 0x24, 0xe3, 0x2f, 0xe5, 0x32, 0x1e, 0x43, 0x77, 0xc7, 0x22,
|
||||
0x81, 0x2e, 0xd6, 0x68, 0x1e, 0xa8, 0xe9, 0x31, 0xf4, 0x22, 0xb4, 0xc6, 0x87, 0x86, 0xeb, 0x62,
|
||||
0x7b, 0xe8, 0x1a, 0x0e, 0x17, 0x40, 0x43, 0x6f, 0x0a, 0xd8, 0x9e, 0xe1, 0x60, 0xf4, 0x1c, 0xd4,
|
||||
0xa9, 0xcb, 0x0e, 0x2d, 0x53, 0xaa, 0x7f, 0x99, 0xb9, 0xb0, 0x49, 0xd0, 0x45, 0x00, 0x36, 0x64,
|
||||
0x98, 0xa6, 0xcf, 0xd3, 0x68, 0x43, 0x6f, 0x50, 0xc8, 0x0d, 0x0a, 0xd0, 0x7e, 0xaa, 0x40, 0x8b,
|
||||
0xc6, 0xec, 0xbb, 0x38, 0x30, 0xa8, 0x1e, 0xd0, 0x5b, 0xd0, 0xb0, 0x3d, 0xc3, 0x1c, 0x06, 0xc7,
|
||||
0x53, 0x8e, 0xaa, 0x93, 0x96, 0x35, 0x67, 0x81, 0x2e, 0xba, 0x77, 0x3c, 0xc5, 0x7a, 0xdd, 0x16,
|
||||
0x5f, 0x8b, 0xc8, 0x3b, 0xe3, 0xca, 0xe5, 0x1c, 0x57, 0xfe, 0x7e, 0x15, 0x56, 0xbf, 0x6d, 0x04,
|
||||
0xe3, 0xc3, 0x6d, 0x67, 0x8b, 0x33, 0x79, 0x0a, 0x23, 0x88, 0x62, 0x5b, 0x29, 0x1e, 0xdb, 0x3e,
|
||||
0xb5, 0xd8, 0x19, 0xda, 0x79, 0x35, 0xcf, 0xce, 0x69, 0x91, 0xbd, 0xf1, 0xbe, 0x50, 0x55, 0xcc,
|
||||
0xce, 0x63, 0x39, 0xa8, 0xf6, 0x34, 0x39, 0x68, 0x0b, 0xda, 0xf8, 0xc3, 0xb1, 0x3d, 0xa3, 0x3a,
|
||||
0x67, 0xd8, 0x97, 0x19, 0xf6, 0xe7, 0x73, 0xb0, 0xc7, 0x9d, 0xac, 0x25, 0x16, 0xed, 0x0a, 0x1a,
|
||||
0xb8, 0xaa, 0x1d, 0x1c, 0x18, 0xbd, 0x3a, 0x23, 0xe3, 0x52, 0x91, 0xaa, 0xa5, 0x7d, 0x70, 0x75,
|
||||
0xd3, 0x3f, 0x74, 0x01, 0x1a, 0x22, 0xe3, 0xed, 0x6e, 0xf7, 0x1a, 0x4c, 0x7c, 0x11, 0x00, 0x19,
|
||||
0xd0, 0x16, 0x11, 0x48, 0x50, 0x08, 0x8c, 0xc2, 0xb7, 0xf3, 0x10, 0xe4, 0x2b, 0x3b, 0x4e, 0x39,
|
||||
0x79, 0xc7, 0x0d, 0xfc, 0x63, 0xbd, 0x45, 0x62, 0xa0, 0xfe, 0x10, 0xce, 0x64, 0xa6, 0x20, 0x15,
|
||||
0xca, 0x0f, 0xf1, 0x31, 0x33, 0x90, 0xb2, 0x4e, 0x3f, 0xd1, 0xeb, 0x50, 0x3d, 0x32, 0xec, 0x19,
|
||||
0x66, 0x06, 0x30, 0x5f, 0x46, 0x7c, 0xf2, 0x57, 0x4b, 0x6f, 0x2a, 0xda, 0xc7, 0x25, 0x78, 0x8e,
|
||||
0xd3, 0x86, 0xed, 0xc0, 0xf8, 0x7c, 0x6d, 0x31, 0xb4, 0xb3, 0xca, 0x89, 0xec, 0xec, 0x22, 0x80,
|
||||
0x2c, 0x56, 0x2c, 0x53, 0xa4, 0xf7, 0x50, 0x4b, 0x66, 0xd2, 0x04, 0x1a, 0x27, 0x35, 0x01, 0xed,
|
||||
0x8f, 0x15, 0xe8, 0x0a, 0xd9, 0xd1, 0x19, 0x2c, 0x80, 0x5c, 0x80, 0x46, 0x98, 0x7a, 0x84, 0x1a,
|
||||
0x22, 0x00, 0xba, 0x04, 0xcd, 0x98, 0xfb, 0x08, 0x39, 0xc4, 0x41, 0x0b, 0x09, 0x43, 0x16, 0x12,
|
||||
0x95, 0x58, 0x21, 0x71, 0x11, 0xe0, 0xc0, 0x9e, 0x91, 0xc3, 0x61, 0x60, 0x39, 0x58, 0x72, 0xca,
|
||||
0x20, 0xf7, 0x2c, 0x07, 0xa3, 0x1b, 0xd0, 0x1a, 0x59, 0xae, 0xed, 0x4d, 0x86, 0x53, 0x23, 0x38,
|
||||
0x24, 0xbd, 0x5a, 0xa1, 0xc3, 0xdc, 0xb2, 0xb0, 0x6d, 0xde, 0x64, 0x73, 0xf5, 0x26, 0x5f, 0xb3,
|
||||
0x4f, 0x97, 0xa0, 0xe7, 0xa1, 0xe9, 0xce, 0x9c, 0xa1, 0x77, 0x30, 0xf4, 0xbd, 0xc7, 0xd4, 0xe5,
|
||||
0x18, 0x0a, 0x77, 0xe6, 0xbc, 0x77, 0xa0, 0x7b, 0x8f, 0x69, 0xe8, 0x6f, 0xd0, 0x24, 0x40, 0x6c,
|
||||
0x6f, 0x42, 0x7a, 0xf5, 0x85, 0xf6, 0x8f, 0x16, 0xd0, 0xd5, 0x26, 0x35, 0x33, 0xb6, 0xba, 0xb1,
|
||||
0xd8, 0xea, 0x70, 0x01, 0x7a, 0x19, 0x3a, 0x63, 0xcf, 0x99, 0x1a, 0x4c, 0x42, 0xb7, 0x7c, 0xcf,
|
||||
0x61, 0xfe, 0x56, 0xd6, 0x53, 0x50, 0xb4, 0x05, 0x4d, 0xcb, 0x35, 0xf1, 0x87, 0xc2, 0x29, 0x9b,
|
||||
0x0c, 0x8f, 0x96, 0xa7, 0x72, 0x86, 0x68, 0x97, 0xce, 0x65, 0x4a, 0x07, 0x4b, 0x7e, 0x12, 0x9a,
|
||||
0x91, 0xa4, 0x6f, 0x13, 0xeb, 0x23, 0xdc, 0x6b, 0x71, 0x2d, 0x0a, 0xd8, 0xc0, 0xfa, 0x08, 0xd3,
|
||||
0x22, 0xd9, 0x72, 0x09, 0xf6, 0x83, 0xa1, 0x30, 0xca, 0x5e, 0x9b, 0xa5, 0xad, 0x36, 0x87, 0x0a,
|
||||
0x5f, 0xd2, 0x7e, 0x5b, 0x82, 0x4e, 0x12, 0x11, 0xea, 0xc1, 0xf2, 0x01, 0x83, 0x48, 0xeb, 0x91,
|
||||
0xbf, 0x14, 0x2d, 0x76, 0x69, 0x07, 0x3d, 0x64, 0xb4, 0x30, 0xe3, 0xa9, 0xeb, 0x4d, 0x0e, 0x63,
|
||||
0x1b, 0x50, 0x23, 0xe0, 0xec, 0xb1, 0x4c, 0x59, 0x66, 0x28, 0x1b, 0x0c, 0xc2, 0xf2, 0x64, 0x0f,
|
||||
0x96, 0x39, 0x1b, 0xd2, 0x74, 0xe4, 0x2f, 0x1d, 0x19, 0xcd, 0x2c, 0x86, 0x95, 0x9b, 0x8e, 0xfc,
|
||||
0x45, 0xdb, 0xd0, 0xe2, 0x5b, 0x4e, 0x0d, 0xdf, 0x70, 0xa4, 0xe1, 0xbc, 0x98, 0xeb, 0xee, 0xb7,
|
||||
0xf1, 0xf1, 0xfb, 0x34, 0x7a, 0xec, 0x1b, 0x96, 0xaf, 0x73, 0x41, 0xef, 0xb3, 0x55, 0x68, 0x0d,
|
||||
0x54, 0xbe, 0xcb, 0x81, 0x65, 0x63, 0x61, 0x82, 0xcb, 0x2c, 0x19, 0x77, 0x18, 0xfc, 0x96, 0x65,
|
||||
0x63, 0x6e, 0x65, 0x21, 0x0b, 0x4c, 0xb4, 0x75, 0x6e, 0x64, 0x0c, 0x42, 0x05, 0xab, 0xfd, 0xb5,
|
||||
0x0c, 0x2b, 0xd4, 0xd7, 0x84, 0xdb, 0x9d, 0x22, 0x1a, 0x5d, 0x04, 0x30, 0x49, 0x30, 0x4c, 0x44,
|
||||
0xa4, 0x86, 0x49, 0x82, 0x3d, 0x1e, 0x94, 0xde, 0x92, 0x01, 0xa7, 0x5c, 0x5c, 0xeb, 0xa6, 0x7c,
|
||||
0x3f, 0x9b, 0xdc, 0x9e, 0xaa, 0x1b, 0xbe, 0x0c, 0x6d, 0xe2, 0xcd, 0xfc, 0x31, 0x1e, 0x26, 0xba,
|
||||
0x92, 0x16, 0x07, 0xee, 0xe5, 0xc7, 0xcc, 0x5a, 0x6e, 0x57, 0x1e, 0x8b, 0x6e, 0xcb, 0xa7, 0x4b,
|
||||
0x70, 0xf5, 0x74, 0x82, 0xbb, 0x0d, 0x5d, 0xe6, 0x7e, 0xc3, 0xa9, 0x47, 0x78, 0x73, 0x27, 0xbc,
|
||||
0x36, 0xe5, 0x4d, 0xe1, 0x29, 0xdc, 0x5d, 0x32, 0xd9, 0x17, 0x53, 0xf5, 0x0e, 0x5b, 0x2a, 0x7f,
|
||||
0x89, 0xf6, 0xb3, 0x12, 0xac, 0x8a, 0x66, 0xf1, 0xf4, 0x8a, 0x2d, 0x4a, 0x33, 0x32, 0x6a, 0x96,
|
||||
0x9f, 0xd0, 0x7e, 0x55, 0x16, 0x28, 0x83, 0xaa, 0x39, 0x65, 0x50, 0xb2, 0x05, 0xa9, 0x65, 0x5a,
|
||||
0x90, 0xeb, 0x50, 0x25, 0x63, 0x6f, 0x8a, 0x99, 0x1a, 0x3a, 0x9b, 0x17, 0xf3, 0xd4, 0xb0, 0x6d,
|
||||
0x04, 0xc6, 0x80, 0x4e, 0xd2, 0xf9, 0x5c, 0xed, 0x1f, 0x0a, 0xb4, 0x07, 0xd8, 0xf0, 0xc7, 0x87,
|
||||
0x52, 0x18, 0x6f, 0x40, 0xd9, 0xc7, 0x8f, 0x84, 0x2c, 0x5e, 0x2a, 0x10, 0x74, 0x62, 0x89, 0x4e,
|
||||
0x17, 0xd0, 0xd0, 0x61, 0x3a, 0xb6, 0x8c, 0x45, 0xbc, 0x48, 0x6e, 0xe8, 0x4d, 0xd3, 0xb1, 0x65,
|
||||
0x56, 0x4f, 0x71, 0x50, 0xce, 0x70, 0xb0, 0x0e, 0x67, 0x0e, 0x7c, 0xcf, 0x19, 0xb2, 0x4a, 0x7d,
|
||||
0x68, 0xb3, 0x02, 0x9d, 0x89, 0xab, 0xae, 0x77, 0xe9, 0x40, 0xac, 0x6e, 0x8f, 0xb8, 0xad, 0x9e,
|
||||
0x80, 0xdb, 0x7f, 0x2a, 0xd0, 0xfa, 0x16, 0x1d, 0x92, 0xcc, 0xbe, 0x19, 0x67, 0xf6, 0xe5, 0x02,
|
||||
0x66, 0x75, 0x1c, 0xf8, 0x16, 0x3e, 0xc2, 0xff, 0x75, 0xec, 0xfe, 0x59, 0x81, 0xfe, 0xe0, 0xd8,
|
||||
0x1d, 0xeb, 0xdc, 0xa3, 0x4e, 0x6f, 0xf6, 0x97, 0xa1, 0x7d, 0x94, 0x68, 0x94, 0x4a, 0x2c, 0xfc,
|
||||
0xb7, 0x8e, 0xe2, 0x9d, 0x92, 0x0e, 0xaa, 0xac, 0x87, 0x04, 0xb3, 0x32, 0xc0, 0xbd, 0x92, 0x47,
|
||||
0x75, 0x8a, 0x38, 0x16, 0x20, 0xba, 0x7e, 0x12, 0xa8, 0xf9, 0xb0, 0x92, 0x33, 0x0f, 0x9d, 0x87,
|
||||
0x65, 0xd1, 0x94, 0x89, 0x44, 0xc6, 0xfd, 0xd0, 0xa4, 0xda, 0x89, 0x8e, 0x15, 0x2c, 0x33, 0x5b,
|
||||
0x04, 0x99, 0xe8, 0x05, 0x68, 0x86, 0xd5, 0xb3, 0x99, 0x51, 0x8f, 0x49, 0xb4, 0x3f, 0x28, 0xb0,
|
||||
0xfa, 0xae, 0xe1, 0x9a, 0xde, 0xc1, 0xc1, 0xe9, 0x25, 0xb7, 0x05, 0x89, 0xc2, 0x7a, 0xd1, 0x96,
|
||||
0x3d, 0xb1, 0x08, 0xbd, 0x0a, 0x67, 0x7c, 0x1e, 0xc1, 0xcc, 0xa4, 0x68, 0xcb, 0xba, 0x2a, 0x07,
|
||||
0x42, 0x91, 0xfd, 0xa6, 0x04, 0x88, 0x46, 0xdd, 0x9b, 0x86, 0x6d, 0xb8, 0x63, 0xfc, 0xf4, 0xa4,
|
||||
0x5f, 0x81, 0x4e, 0x22, 0x57, 0x84, 0xa7, 0xfb, 0xf1, 0x64, 0x41, 0xd0, 0x6d, 0xe8, 0x8c, 0x38,
|
||||
0xaa, 0xa1, 0x8f, 0x0d, 0xe2, 0xb9, 0x2c, 0x08, 0x76, 0xf2, 0xbb, 0xf3, 0x7b, 0xbe, 0x35, 0x99,
|
||||
0x60, 0x7f, 0xcb, 0x73, 0x4d, 0x1e, 0xad, 0xdb, 0x23, 0x49, 0x26, 0x5d, 0x4a, 0x95, 0x13, 0x25,
|
||||
0x4e, 0xd9, 0x15, 0x42, 0x98, 0x39, 0x99, 0x28, 0x08, 0x36, 0xec, 0x48, 0x10, 0x51, 0xd4, 0x54,
|
||||
0xf9, 0xc0, 0xa0, 0xf8, 0x70, 0x26, 0x27, 0x91, 0x69, 0xbf, 0x53, 0x00, 0x85, 0xfd, 0x11, 0xeb,
|
||||
0x48, 0x98, 0x85, 0xa5, 0x97, 0x2a, 0x39, 0xc1, 0xfb, 0x02, 0x34, 0x4c, 0xb9, 0x52, 0x78, 0x44,
|
||||
0x04, 0xa0, 0x3e, 0xc3, 0xd9, 0x18, 0xd2, 0xac, 0x87, 0x4d, 0x59, 0x6d, 0x73, 0xe0, 0x1d, 0x06,
|
||||
0x4b, 0xe6, 0xc1, 0x4a, 0x3a, 0x0f, 0xc6, 0xcf, 0x1e, 0xaa, 0x89, 0xb3, 0x07, 0xed, 0x93, 0x12,
|
||||
0xa8, 0x2c, 0xa2, 0x6d, 0x45, 0x8d, 0xc9, 0x42, 0x44, 0x5f, 0x86, 0xb6, 0xb8, 0xff, 0x4a, 0x10,
|
||||
0xde, 0x7a, 0x14, 0xdb, 0x0c, 0x5d, 0x83, 0xb3, 0x7c, 0x92, 0x8f, 0xc9, 0xcc, 0x8e, 0x0a, 0x4d,
|
||||
0x5e, 0xf5, 0xa1, 0x47, 0x3c, 0x94, 0xd2, 0x21, 0xb9, 0xe2, 0x3e, 0xac, 0x4e, 0x6c, 0x6f, 0x64,
|
||||
0xd8, 0xc3, 0xa4, 0x7a, 0x0a, 0x9a, 0xaa, 0xac, 0xc5, 0x9f, 0xe5, 0xcb, 0x07, 0x71, 0x1d, 0x12,
|
||||
0xb4, 0x43, 0x5b, 0x5d, 0xfc, 0x30, 0x2c, 0x04, 0xc4, 0xb1, 0xf2, 0x22, 0x75, 0x40, 0x8b, 0x2e,
|
||||
0x94, 0x7f, 0xda, 0xc7, 0x0a, 0x74, 0x53, 0xc7, 0x87, 0xe9, 0x86, 0x49, 0xc9, 0x36, 0x4c, 0x6f,
|
||||
0x42, 0x95, 0x76, 0x11, 0x3c, 0xde, 0x75, 0xf2, 0x8b, 0xf9, 0xe4, 0xae, 0x3a, 0x5f, 0x80, 0xae,
|
||||
0xc2, 0x4a, 0xce, 0x65, 0x8b, 0xb0, 0x01, 0x94, 0xbd, 0x6b, 0xd1, 0x7e, 0x5f, 0x81, 0x66, 0x4c,
|
||||
0x1e, 0x73, 0x7a, 0xbd, 0x45, 0xce, 0x83, 0x52, 0xec, 0x95, 0xb3, 0xec, 0x15, 0xdc, 0x36, 0x50,
|
||||
0xbb, 0x73, 0xb0, 0xc3, 0xab, 0x64, 0x51, 0xb2, 0x3b, 0xd8, 0x61, 0xcd, 0x07, 0x35, 0xc9, 0x99,
|
||||
0xc3, 0xbb, 0x34, 0xee, 0x4e, 0xcb, 0xee, 0xcc, 0x61, 0x3d, 0x5a, 0xb2, 0x41, 0x58, 0x7e, 0x42,
|
||||
0x83, 0x50, 0x4f, 0x36, 0x08, 0x09, 0x3f, 0x6a, 0xa4, 0xfd, 0x68, 0xd1, 0xf6, 0xeb, 0x1a, 0xac,
|
||||
0x8c, 0x7d, 0x6c, 0x04, 0xd8, 0xbc, 0x79, 0xbc, 0x15, 0x0e, 0xf5, 0x9a, 0x2c, 0xaf, 0xe6, 0x0d,
|
||||
0xa1, 0x5b, 0xd1, 0x39, 0x0a, 0xd7, 0x72, 0x8b, 0x69, 0x39, 0xbf, 0xff, 0x10, 0xba, 0xe1, 0x4a,
|
||||
0x96, 0xe1, 0x99, 0xfd, 0xa5, 0x1b, 0xbf, 0xf6, 0x53, 0x35, 0x7e, 0x2f, 0x40, 0x33, 0x3a, 0x4d,
|
||||
0x20, 0xbd, 0x0e, 0x8f, 0x7c, 0xe1, 0x71, 0x02, 0x49, 0x04, 0x83, 0x6e, 0x32, 0x18, 0xfc, 0xa5,
|
||||
0x0c, 0x9d, 0xa8, 0xe4, 0x5f, 0x38, 0x14, 0x2c, 0x72, 0x69, 0xb8, 0x07, 0x6a, 0x94, 0x50, 0x99,
|
||||
0x94, 0x9e, 0xd8, 0xb5, 0xa4, 0x4f, 0xe8, 0xbb, 0xd3, 0x94, 0xcf, 0x25, 0xce, 0x40, 0x2b, 0x27,
|
||||
0x3a, 0x03, 0x3d, 0xe5, 0xdd, 0xd2, 0x75, 0x38, 0x17, 0x26, 0xd1, 0x04, 0xdb, 0xbc, 0xa2, 0x3e,
|
||||
0x2b, 0x07, 0xf7, 0xe3, 0xec, 0x17, 0xb8, 0xf1, 0x72, 0x91, 0x1b, 0xa7, 0xd5, 0x58, 0xcf, 0xa8,
|
||||
0x31, 0x7b, 0xc5, 0xd5, 0xc8, 0xbb, 0xe2, 0xba, 0x0f, 0x2b, 0xf7, 0x5d, 0x32, 0x1b, 0x91, 0xb1,
|
||||
0x6f, 0x8d, 0x70, 0x58, 0x5a, 0x2e, 0xa2, 0xd6, 0x3e, 0xd4, 0x53, 0xd5, 0x69, 0xf8, 0xaf, 0xfd,
|
||||
0x50, 0x81, 0xd5, 0xec, 0xbe, 0xcc, 0x62, 0xa2, 0x60, 0xa0, 0x24, 0x82, 0xc1, 0x77, 0x60, 0x25,
|
||||
0xda, 0x3e, 0x59, 0xf7, 0x16, 0x54, 0x76, 0x39, 0x84, 0xeb, 0x28, 0xda, 0x43, 0xc2, 0xb4, 0x7f,
|
||||
0x29, 0xe1, 0x29, 0x23, 0x85, 0x4d, 0xd8, 0xd9, 0x29, 0x4d, 0x50, 0x9e, 0x6b, 0x5b, 0x6e, 0xd8,
|
||||
0xa2, 0x0a, 0x1e, 0x39, 0x50, 0xb4, 0xa8, 0xef, 0x42, 0x57, 0x4c, 0x0a, 0xf3, 0xcc, 0x82, 0x95,
|
||||
0x55, 0x87, 0xaf, 0x0b, 0x33, 0xcc, 0x15, 0xe8, 0x78, 0x07, 0x07, 0x71, 0x7c, 0x3c, 0x50, 0xb6,
|
||||
0x05, 0x54, 0x20, 0xfc, 0x26, 0xa8, 0x72, 0xda, 0x49, 0x33, 0x5b, 0x57, 0x2c, 0x0c, 0x2b, 0xb4,
|
||||
0x1f, 0x28, 0xd0, 0x4b, 0xe6, 0xb9, 0x18, 0xfb, 0x27, 0xaf, 0xd3, 0xbe, 0x96, 0xbc, 0x0e, 0xba,
|
||||
0xf2, 0x04, 0x7a, 0x22, 0x3c, 0xe2, 0x3c, 0x61, 0xfd, 0x1b, 0xd0, 0x08, 0xdb, 0x07, 0xd4, 0x84,
|
||||
0xe5, 0xfb, 0xee, 0x6d, 0xd7, 0x7b, 0xec, 0xaa, 0x4b, 0x68, 0x19, 0xca, 0x37, 0x6c, 0x5b, 0x55,
|
||||
0x50, 0x1b, 0x1a, 0x83, 0xc0, 0xc7, 0x86, 0x63, 0xb9, 0x13, 0xb5, 0x84, 0x3a, 0x00, 0xef, 0x5a,
|
||||
0x24, 0xf0, 0x7c, 0x6b, 0x6c, 0xd8, 0x6a, 0x79, 0xfd, 0x23, 0xe8, 0x24, 0xbd, 0x1e, 0xb5, 0xa0,
|
||||
0xbe, 0xe7, 0x05, 0xef, 0x7c, 0x68, 0x91, 0x40, 0x5d, 0xa2, 0xf3, 0xf7, 0xbc, 0x60, 0xdf, 0xc7,
|
||||
0x04, 0xbb, 0x81, 0xaa, 0x20, 0x80, 0xda, 0x7b, 0xee, 0xb6, 0x45, 0x1e, 0xaa, 0x25, 0xb4, 0x22,
|
||||
0x92, 0xb2, 0x61, 0xef, 0x0a, 0x57, 0x52, 0xcb, 0x74, 0x79, 0xf8, 0x57, 0x41, 0x2a, 0xb4, 0xc2,
|
||||
0x29, 0x3b, 0xfb, 0xf7, 0xd5, 0x2a, 0x6a, 0x40, 0x95, 0x7f, 0xd6, 0xd6, 0x4d, 0x50, 0xd3, 0x15,
|
||||
0x25, 0xdd, 0x93, 0x33, 0x11, 0x82, 0xd4, 0x25, 0xca, 0x99, 0x28, 0xe9, 0x55, 0x05, 0x75, 0xa1,
|
||||
0x19, 0x2b, 0x90, 0xd5, 0x12, 0x05, 0xec, 0xf8, 0xd3, 0xb1, 0x28, 0x95, 0x39, 0x09, 0x54, 0xef,
|
||||
0xdb, 0x54, 0x12, 0x95, 0xf5, 0x9b, 0x50, 0x97, 0xe1, 0x88, 0x4e, 0x15, 0x22, 0xa2, 0xbf, 0xea,
|
||||
0x12, 0x3a, 0x03, 0xed, 0xc4, 0xc5, 0xbc, 0xaa, 0x20, 0x04, 0x9d, 0xe4, 0xa3, 0x09, 0xb5, 0xb4,
|
||||
0xf9, 0x8b, 0x16, 0x00, 0xaf, 0xd7, 0x3c, 0xcf, 0x37, 0xd1, 0x14, 0xd0, 0x0e, 0x0e, 0x68, 0x2e,
|
||||
0xf2, 0x5c, 0x99, 0x47, 0x08, 0xba, 0x56, 0x50, 0xd6, 0x64, 0xa7, 0x0a, 0x52, 0xfb, 0x45, 0xad,
|
||||
0x6b, 0x6a, 0xba, 0xb6, 0x84, 0x1c, 0x86, 0xf1, 0x9e, 0xe5, 0xe0, 0x7b, 0xd6, 0xf8, 0x61, 0x58,
|
||||
0xe8, 0x15, 0x63, 0x4c, 0x4d, 0x95, 0x18, 0x53, 0x61, 0x5f, 0xfc, 0x0c, 0x02, 0xdf, 0x72, 0x27,
|
||||
0xf2, 0x7a, 0x4f, 0x5b, 0x42, 0x8f, 0xe0, 0xec, 0x0e, 0x66, 0xd8, 0x2d, 0x12, 0x58, 0x63, 0x22,
|
||||
0x11, 0x6e, 0x16, 0x23, 0xcc, 0x4c, 0x3e, 0x21, 0x4a, 0x1b, 0xba, 0xa9, 0xc7, 0x4d, 0x68, 0x3d,
|
||||
0xff, 0x86, 0x30, 0xef, 0x21, 0x56, 0xff, 0xd5, 0x85, 0xe6, 0x86, 0xd8, 0x2c, 0xe8, 0x24, 0x1f,
|
||||
0xf0, 0xa0, 0xff, 0x2f, 0xda, 0x20, 0xf3, 0x46, 0xa1, 0xbf, 0xbe, 0xc8, 0xd4, 0x10, 0xd5, 0x03,
|
||||
0x6e, 0x4f, 0xf3, 0x50, 0xe5, 0xbe, 0x0f, 0xe9, 0x3f, 0xe9, 0x66, 0x55, 0x5b, 0x42, 0xdf, 0x85,
|
||||
0x33, 0x99, 0x97, 0x14, 0xe8, 0x4b, 0xf9, 0xfd, 0x7a, 0xfe, 0x83, 0x8b, 0x79, 0x18, 0x1e, 0xa4,
|
||||
0xbd, 0xa1, 0x98, 0xfa, 0xcc, 0xcb, 0x9b, 0xc5, 0xa9, 0x8f, 0x6d, 0xff, 0x24, 0xea, 0x4f, 0x8c,
|
||||
0x61, 0xc6, 0xdc, 0x26, 0xdd, 0x39, 0xbc, 0x96, 0x87, 0xa2, 0xf0, 0x39, 0x47, 0x7f, 0x63, 0xd1,
|
||||
0xe9, 0x71, 0xeb, 0x4a, 0xbe, 0x18, 0xc8, 0x17, 0x5a, 0xee, 0x2b, 0x87, 0x7c, 0xeb, 0xca, 0x7f,
|
||||
0x80, 0xa0, 0x2d, 0xa1, 0x7b, 0x89, 0x68, 0x88, 0x5e, 0x2e, 0x52, 0x4e, 0xf2, 0x3c, 0x61, 0x9e,
|
||||
0xdc, 0x86, 0x00, 0x3b, 0x38, 0xb8, 0x8b, 0x03, 0xdf, 0x1a, 0x93, 0xf4, 0xa6, 0xe2, 0x27, 0x9a,
|
||||
0x20, 0x37, 0x7d, 0x65, 0xee, 0xbc, 0x90, 0xec, 0x11, 0x34, 0x77, 0x70, 0x20, 0x0e, 0x87, 0x08,
|
||||
0x2a, 0x5c, 0x29, 0x67, 0x48, 0x14, 0x6b, 0xf3, 0x27, 0xc6, 0x23, 0x4a, 0xea, 0x01, 0x03, 0x2a,
|
||||
0x94, 0x6d, 0xf6, 0x59, 0x45, 0x7e, 0x44, 0x29, 0x78, 0x11, 0xa1, 0x2d, 0x6d, 0xfe, 0x1b, 0xa0,
|
||||
0xc1, 0x52, 0x04, 0x4d, 0x3d, 0xff, 0xcb, 0x10, 0xcf, 0x20, 0x43, 0x7c, 0x00, 0xdd, 0xd4, 0x7d,
|
||||
0x78, 0xbe, 0x3e, 0xf3, 0x2f, 0xcd, 0xe7, 0x99, 0xfc, 0x08, 0x50, 0xf6, 0x46, 0x3b, 0x3f, 0x54,
|
||||
0x14, 0xde, 0x7c, 0xcf, 0xc3, 0xf1, 0x3e, 0x7f, 0x52, 0x12, 0x56, 0xaf, 0xaf, 0x14, 0x79, 0x6b,
|
||||
0xea, 0xe4, 0xf2, 0xf3, 0x0f, 0xa4, 0xcf, 0x3e, 0xd1, 0x7c, 0x00, 0xdd, 0xd4, 0x3d, 0x4f, 0xbe,
|
||||
0x76, 0xf3, 0x2f, 0x83, 0xe6, 0xed, 0xfe, 0x19, 0x46, 0x64, 0x13, 0x56, 0x72, 0x4e, 0xef, 0x51,
|
||||
0x6e, 0x16, 0x29, 0x3e, 0xe6, 0x9f, 0xc7, 0xd0, 0x00, 0x6a, 0xfc, 0x36, 0x07, 0xbd, 0x98, 0xdf,
|
||||
0x31, 0xc4, 0x6e, 0x7a, 0xfa, 0xf3, 0xee, 0x83, 0xc8, 0xcc, 0x0e, 0xf8, 0xa6, 0x55, 0x16, 0xc2,
|
||||
0x50, 0xee, 0x65, 0x60, 0xfc, 0x0a, 0xa6, 0x3f, 0xff, 0xd6, 0x45, 0x6e, 0xfa, 0xac, 0x73, 0xc9,
|
||||
0xcd, 0xd7, 0x1f, 0x6c, 0x4e, 0xac, 0xe0, 0x70, 0x36, 0xa2, 0x42, 0xba, 0xca, 0x67, 0xbe, 0x66,
|
||||
0x79, 0xe2, 0xeb, 0xaa, 0x24, 0xed, 0x2a, 0xdb, 0xe9, 0x2a, 0xe3, 0x65, 0x3a, 0x1a, 0xd5, 0xd8,
|
||||
0xef, 0xf5, 0xff, 0x04, 0x00, 0x00, 0xff, 0xff, 0xab, 0x05, 0x7f, 0x12, 0x50, 0x30, 0x00, 0x00,
|
||||
}
|
||||
|
||||
// Reference imports to suppress errors if they are not otherwise used.
|
||||
|
|
|
@ -2663,7 +2663,7 @@ func (node *Proxy) Query(ctx context.Context, request *milvuspb.QueryRequest) (*
|
|||
},
|
||||
request: request,
|
||||
qc: node.queryCoord,
|
||||
queryShardPolicy: roundRobinPolicy,
|
||||
queryShardPolicy: mergeRoundRobinPolicy,
|
||||
shardMgr: node.shardMgr,
|
||||
}
|
||||
|
||||
|
@ -3076,7 +3076,7 @@ func (node *Proxy) CalcDistance(ctx context.Context, request *milvuspb.CalcDista
|
|||
qc: node.queryCoord,
|
||||
ids: ids.IdArray,
|
||||
|
||||
queryShardPolicy: roundRobinPolicy,
|
||||
queryShardPolicy: mergeRoundRobinPolicy,
|
||||
shardMgr: node.shardMgr,
|
||||
}
|
||||
|
||||
|
|
|
@ -39,13 +39,21 @@ type QueryNodeMock struct {
|
|||
|
||||
withSearchResult *internalpb.SearchResults
|
||||
withQueryResult *internalpb.RetrieveResults
|
||||
queryError error
|
||||
searchError error
|
||||
}
|
||||
|
||||
func (m *QueryNodeMock) Search(ctx context.Context, req *querypb.SearchRequest) (*internalpb.SearchResults, error) {
|
||||
if m.searchError != nil {
|
||||
return nil, m.searchError
|
||||
}
|
||||
return m.withSearchResult, nil
|
||||
}
|
||||
|
||||
func (m *QueryNodeMock) Query(ctx context.Context, req *querypb.QueryRequest) (*internalpb.RetrieveResults, error) {
|
||||
if m.queryError != nil {
|
||||
return nil, m.queryError
|
||||
}
|
||||
return m.withQueryResult, nil
|
||||
}
|
||||
|
||||
|
|
|
@ -4,6 +4,7 @@ import (
|
|||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"sync"
|
||||
|
||||
"github.com/milvus-io/milvus/internal/log"
|
||||
"github.com/milvus-io/milvus/internal/types"
|
||||
|
@ -11,7 +12,9 @@ import (
|
|||
"go.uber.org/zap"
|
||||
)
|
||||
|
||||
type pickShardPolicy func(ctx context.Context, mgr *shardClientMgr, query func(UniqueID, types.QueryNode) error, leaders []nodeInfo) error
|
||||
// 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
|
||||
|
||||
var (
|
||||
errBegin = errors.New("begin error")
|
||||
|
@ -28,44 +31,115 @@ func updateShardsWithRoundRobin(shardsLeaders map[string][]nodeInfo) {
|
|||
}
|
||||
}
|
||||
|
||||
func roundRobinPolicy(ctx context.Context, mgr *shardClientMgr, query func(UniqueID, types.QueryNode) error, leaders []nodeInfo) error {
|
||||
var (
|
||||
err = errBegin
|
||||
current = 0
|
||||
qn types.QueryNode
|
||||
)
|
||||
replicaNum := len(leaders)
|
||||
|
||||
for err != nil && current < replicaNum {
|
||||
currentID := leaders[current].nodeID
|
||||
if err != errBegin {
|
||||
log.Warn("retry with another QueryNode",
|
||||
zap.Int("retries numbers", current),
|
||||
zap.Int64("nodeID", currentID))
|
||||
// group dml shard leader with same nodeID
|
||||
func groupShardleadersWithSameQueryNode(
|
||||
ctx context.Context,
|
||||
shard2leaders map[string][]nodeInfo,
|
||||
nexts map[string]int, errSet map[string]error,
|
||||
mgr *shardClientMgr) (map[int64][]string, map[int64]types.QueryNode, error) {
|
||||
// check if all leaders were checked
|
||||
for dml, idx := range nexts {
|
||||
if idx >= len(shard2leaders[dml]) {
|
||||
log.Warn("no shard leaders were available",
|
||||
zap.String("channel", dml),
|
||||
zap.String("leaders", fmt.Sprintf("%v", shard2leaders[dml])))
|
||||
if e, ok := errSet[dml]; ok {
|
||||
return nil, nil, e // return last error recorded
|
||||
}
|
||||
return nil, nil, fmt.Errorf("no available shard leader")
|
||||
}
|
||||
|
||||
qn, err = mgr.GetClient(ctx, leaders[current].nodeID)
|
||||
if err != nil {
|
||||
log.Warn("fail to get valid QueryNode", zap.Int64("nodeID", currentID),
|
||||
zap.Error(err))
|
||||
current++
|
||||
continue
|
||||
}
|
||||
|
||||
err = query(currentID, qn)
|
||||
if err != nil {
|
||||
log.Warn("fail to Query with shard leader",
|
||||
zap.Int64("nodeID", currentID),
|
||||
zap.Error(err))
|
||||
}
|
||||
current++
|
||||
}
|
||||
qnSet := make(map[int64]types.QueryNode)
|
||||
node2dmls := make(map[int64][]string)
|
||||
updates := make(map[string]int)
|
||||
|
||||
if current == replicaNum && err != nil {
|
||||
log.Warn("no shard leaders available",
|
||||
zap.String("leaders", fmt.Sprintf("%v", leaders)), zap.Error(err))
|
||||
// needs to return the error from query
|
||||
return err
|
||||
for dml, idx := range nexts {
|
||||
updates[dml] = idx + 1
|
||||
nodeInfo := shard2leaders[dml][idx]
|
||||
if _, ok := qnSet[nodeInfo.nodeID]; !ok {
|
||||
qn, err := mgr.GetClient(ctx, nodeInfo.nodeID)
|
||||
if err != nil {
|
||||
log.Warn("failed to get shard leader", zap.Int64("nodeID", nodeInfo.nodeID), zap.Error(err))
|
||||
// if get client failed, just record error and wait for next round to get client and do query
|
||||
errSet[dml] = err
|
||||
continue
|
||||
}
|
||||
qnSet[nodeInfo.nodeID] = qn
|
||||
}
|
||||
if _, ok := node2dmls[nodeInfo.nodeID]; !ok {
|
||||
node2dmls[nodeInfo.nodeID] = make([]string, 0)
|
||||
}
|
||||
node2dmls[nodeInfo.nodeID] = append(node2dmls[nodeInfo.nodeID], dml)
|
||||
}
|
||||
// update idxes
|
||||
for dml, idx := range updates {
|
||||
nexts[dml] = idx
|
||||
}
|
||||
return node2dmls, qnSet, nil
|
||||
}
|
||||
|
||||
// mergeRoundRobinPolicy first group shard leaders with same querynode, then do the query with multiple dml channels
|
||||
// if request failed, it finds shard leader for failed dml channels, and again groups shard leaders and do the query
|
||||
//
|
||||
// Suppose qn0 is the shard leader for dml-channel0 and dml-channel1, if search for dml-channel0 succeeded, but
|
||||
// failed for dml-channel1. In this case, an error returned from qn0, and next shard leaders for dml-channel0 and dml-channel1 will be
|
||||
// retrieved and dml-channel0 therefore will again be searched.
|
||||
//
|
||||
// TODO: In this senario, qn0 should return a partial success results for dml-channel0, and only retrys for dml-channel1
|
||||
func mergeRoundRobinPolicy(
|
||||
ctx context.Context,
|
||||
mgr *shardClientMgr,
|
||||
query func(context.Context, UniqueID, types.QueryNode, []string) error,
|
||||
dml2leaders map[string][]nodeInfo) error {
|
||||
nexts := make(map[string]int)
|
||||
errSet := make(map[string]error) // record err for dml channels
|
||||
for dml := range dml2leaders {
|
||||
nexts[dml] = 0
|
||||
}
|
||||
for len(nexts) > 0 {
|
||||
node2dmls, nodeset, err := groupShardleadersWithSameQueryNode(ctx, dml2leaders, nexts, errSet, mgr)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
wg := &sync.WaitGroup{}
|
||||
mu := &sync.Mutex{}
|
||||
wg.Add(len(node2dmls))
|
||||
for nodeID, channels := range node2dmls {
|
||||
nodeID := nodeID
|
||||
channels := channels
|
||||
qn := nodeset[nodeID]
|
||||
go func() {
|
||||
defer wg.Done()
|
||||
if err := query(ctx, nodeID, qn, channels); err != nil {
|
||||
log.Warn("failed to do query with node", zap.Int64("nodeID", nodeID),
|
||||
zap.Strings("dmlChannels", channels), zap.Error(err))
|
||||
mu.Lock()
|
||||
defer mu.Unlock()
|
||||
for _, ch := range channels {
|
||||
errSet[ch] = err
|
||||
}
|
||||
return
|
||||
}
|
||||
mu.Lock()
|
||||
defer mu.Unlock()
|
||||
for _, channel := range channels {
|
||||
delete(nexts, channel)
|
||||
delete(errSet, channel)
|
||||
}
|
||||
}()
|
||||
}
|
||||
wg.Wait()
|
||||
if len(nexts) > 0 {
|
||||
nextSet := make(map[string]int64)
|
||||
for dml, idx := range nexts {
|
||||
if idx >= len(dml2leaders[dml]) {
|
||||
nextSet[dml] = -1
|
||||
} else {
|
||||
nextSet[dml] = dml2leaders[dml][idx].nodeID
|
||||
}
|
||||
}
|
||||
log.Warn("retry another query node with round robin", zap.Any("Nexts", nextSet))
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
|
|
@ -3,15 +3,14 @@ package proxy
|
|||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"sort"
|
||||
"sync"
|
||||
"testing"
|
||||
|
||||
"github.com/milvus-io/milvus/internal/log"
|
||||
"github.com/milvus-io/milvus/internal/types"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
"github.com/milvus-io/milvus/internal/util/mock"
|
||||
|
||||
"go.uber.org/zap"
|
||||
)
|
||||
|
@ -54,89 +53,109 @@ func TestUpdateShardsWithRoundRobin(t *testing.T) {
|
|||
})
|
||||
}
|
||||
|
||||
func TestRoundRobinPolicy(t *testing.T) {
|
||||
func TestGroupShardLeadersWithSameQueryNode(t *testing.T) {
|
||||
var err error
|
||||
|
||||
Params.Init()
|
||||
var (
|
||||
ctx = context.TODO()
|
||||
)
|
||||
|
||||
mockCreator := func(ctx context.Context, addr string) (types.QueryNode, error) {
|
||||
return &mock.QueryNodeClient{}, nil
|
||||
mgr := newShardClientMgr()
|
||||
|
||||
shard2leaders := map[string][]nodeInfo{
|
||||
"c0": {{nodeID: 0, address: "fake"}, {nodeID: 1, address: "fake"}, {nodeID: 2, address: "fake"}},
|
||||
"c1": {{nodeID: 1, address: "fake"}, {nodeID: 2, address: "fake"}, {nodeID: 3, address: "fake"}},
|
||||
"c2": {{nodeID: 0, address: "fake"}, {nodeID: 2, address: "fake"}, {nodeID: 3, address: "fake"}},
|
||||
"c3": {{nodeID: 1, address: "fake"}, {nodeID: 3, address: "fake"}, {nodeID: 4, address: "fake"}},
|
||||
}
|
||||
mgr.UpdateShardLeaders(nil, shard2leaders)
|
||||
nexts := map[string]int{
|
||||
"c0": 0,
|
||||
"c1": 0,
|
||||
"c2": 0,
|
||||
"c3": 0,
|
||||
}
|
||||
errSet := map[string]error{}
|
||||
node2dmls, qnSet, err := groupShardleadersWithSameQueryNode(ctx, shard2leaders, nexts, errSet, mgr)
|
||||
assert.Nil(t, err)
|
||||
for nodeID := range node2dmls {
|
||||
sort.Slice(node2dmls[nodeID], func(i, j int) bool { return node2dmls[nodeID][i] < node2dmls[nodeID][j] })
|
||||
}
|
||||
|
||||
mgr := newShardClientMgr(withShardClientCreator(mockCreator))
|
||||
dummyLeaders := genShardLeaderInfo("c1", []UniqueID{-1, 1, 2, 3})
|
||||
mgr.UpdateShardLeaders(nil, dummyLeaders)
|
||||
t.Run("All fails", func(t *testing.T) {
|
||||
allFailTests := []struct {
|
||||
leaderIDs []UniqueID
|
||||
cli0, err := mgr.GetClient(ctx, 0)
|
||||
assert.Nil(t, err)
|
||||
cli1, err := mgr.GetClient(ctx, 1)
|
||||
assert.Nil(t, err)
|
||||
cli2, err := mgr.GetClient(ctx, 2)
|
||||
assert.Nil(t, err)
|
||||
cli3, err := mgr.GetClient(ctx, 3)
|
||||
assert.Nil(t, err)
|
||||
|
||||
description string
|
||||
}{
|
||||
{[]UniqueID{1}, "one invalid shard leader"},
|
||||
{[]UniqueID{1, 2}, "two invalid shard leaders"},
|
||||
{[]UniqueID{1, 1}, "two invalid same shard leaders"},
|
||||
}
|
||||
assert.Equal(t, node2dmls, map[int64][]string{0: {"c0", "c2"}, 1: {"c1", "c3"}})
|
||||
assert.Equal(t, qnSet, map[int64]types.QueryNode{0: cli0, 1: cli1})
|
||||
assert.Equal(t, nexts, map[string]int{"c0": 1, "c1": 1, "c2": 1, "c3": 1})
|
||||
// delete client1 in client mgr
|
||||
delete(mgr.clients.data, 1)
|
||||
node2dmls, qnSet, err = groupShardleadersWithSameQueryNode(ctx, shard2leaders, nexts, errSet, mgr)
|
||||
assert.Nil(t, err)
|
||||
for nodeID := range node2dmls {
|
||||
sort.Slice(node2dmls[nodeID], func(i, j int) bool { return node2dmls[nodeID][i] < node2dmls[nodeID][j] })
|
||||
}
|
||||
assert.Equal(t, node2dmls, map[int64][]string{2: {"c1", "c2"}, 3: {"c3"}})
|
||||
assert.Equal(t, qnSet, map[int64]types.QueryNode{2: cli2, 3: cli3})
|
||||
assert.Equal(t, nexts, map[string]int{"c0": 2, "c1": 2, "c2": 2, "c3": 2})
|
||||
assert.NotNil(t, errSet["c0"])
|
||||
|
||||
for _, test := range allFailTests {
|
||||
t.Run(test.description, func(t *testing.T) {
|
||||
query := (&mockQuery{isvalid: false}).query
|
||||
nexts["c0"] = 3
|
||||
_, _, err = groupShardleadersWithSameQueryNode(ctx, shard2leaders, nexts, errSet, mgr)
|
||||
assert.Equal(t, err, errSet["c0"])
|
||||
|
||||
leaders := make([]nodeInfo, 0, len(test.leaderIDs))
|
||||
for _, ID := range test.leaderIDs {
|
||||
leaders = append(leaders, nodeInfo{ID, "random-addr"})
|
||||
nexts["c0"] = 2
|
||||
nexts["c1"] = 3
|
||||
_, _, err = groupShardleadersWithSameQueryNode(ctx, shard2leaders, nexts, errSet, mgr)
|
||||
assert.Equal(t, err, fmt.Errorf("no available shard leader"))
|
||||
}
|
||||
|
||||
}
|
||||
func TestMergeRoundRobinPolicy(t *testing.T) {
|
||||
var err error
|
||||
|
||||
err := roundRobinPolicy(ctx, mgr, query, leaders)
|
||||
require.Error(t, err)
|
||||
})
|
||||
}
|
||||
})
|
||||
Params.Init()
|
||||
var (
|
||||
ctx = context.TODO()
|
||||
)
|
||||
|
||||
t.Run("Pass at the first try", func(t *testing.T) {
|
||||
allPassTests := []struct {
|
||||
leaderIDs []UniqueID
|
||||
mgr := newShardClientMgr()
|
||||
|
||||
description string
|
||||
}{
|
||||
{[]UniqueID{1}, "one valid shard leader"},
|
||||
{[]UniqueID{1, 2}, "two valid shard leaders"},
|
||||
{[]UniqueID{1, 1}, "two valid same shard leaders"},
|
||||
}
|
||||
shard2leaders := map[string][]nodeInfo{
|
||||
"c0": {{nodeID: 0, address: "fake"}, {nodeID: 1, address: "fake"}, {nodeID: 2, address: "fake"}},
|
||||
"c1": {{nodeID: 1, address: "fake"}, {nodeID: 2, address: "fake"}, {nodeID: 3, address: "fake"}},
|
||||
"c2": {{nodeID: 0, address: "fake"}, {nodeID: 2, address: "fake"}, {nodeID: 3, address: "fake"}},
|
||||
"c3": {{nodeID: 1, address: "fake"}, {nodeID: 3, address: "fake"}, {nodeID: 4, address: "fake"}},
|
||||
}
|
||||
mgr.UpdateShardLeaders(nil, shard2leaders)
|
||||
|
||||
for _, test := range allPassTests {
|
||||
query := (&mockQuery{isvalid: true}).query
|
||||
leaders := make([]nodeInfo, 0, len(test.leaderIDs))
|
||||
for _, ID := range test.leaderIDs {
|
||||
leaders = append(leaders, nodeInfo{ID, "random-addr"})
|
||||
querier := &mockQuery{}
|
||||
querier.init()
|
||||
|
||||
}
|
||||
err := roundRobinPolicy(ctx, mgr, query, leaders)
|
||||
require.NoError(t, err)
|
||||
}
|
||||
})
|
||||
err = mergeRoundRobinPolicy(ctx, mgr, querier.query, shard2leaders)
|
||||
assert.Nil(t, err)
|
||||
assert.Equal(t, querier.records(), map[UniqueID][]string{0: {"c0", "c2"}, 1: {"c1", "c3"}})
|
||||
|
||||
t.Run("Pass at the second try", func(t *testing.T) {
|
||||
passAtLast := []struct {
|
||||
leaderIDs []UniqueID
|
||||
mockerr := fmt.Errorf("mock query node error")
|
||||
querier.init()
|
||||
querier.failset[0] = mockerr
|
||||
|
||||
description string
|
||||
}{
|
||||
{[]UniqueID{-1, 2}, "invalid vs valid shard leaders"},
|
||||
{[]UniqueID{-1, -1, 3}, "invalid, invalid, and valid shard leaders"},
|
||||
}
|
||||
err = mergeRoundRobinPolicy(ctx, mgr, querier.query, shard2leaders)
|
||||
assert.Nil(t, err)
|
||||
assert.Equal(t, querier.records(), map[int64][]string{1: {"c0", "c1", "c3"}, 2: {"c2"}})
|
||||
|
||||
for _, test := range passAtLast {
|
||||
query := (&mockQuery{isvalid: true}).query
|
||||
leaders := make([]nodeInfo, 0, len(test.leaderIDs))
|
||||
for _, ID := range test.leaderIDs {
|
||||
leaders = append(leaders, nodeInfo{ID, "random-addr"})
|
||||
|
||||
}
|
||||
err := roundRobinPolicy(ctx, mgr, query, leaders)
|
||||
require.NoError(t, err)
|
||||
}
|
||||
})
|
||||
querier.init()
|
||||
querier.failset[0] = mockerr
|
||||
querier.failset[2] = mockerr
|
||||
querier.failset[3] = mockerr
|
||||
err = mergeRoundRobinPolicy(ctx, mgr, querier.query, shard2leaders)
|
||||
assert.Equal(t, err, mockerr)
|
||||
}
|
||||
|
||||
func mockQueryNodeCreator(ctx context.Context, address string) (types.QueryNode, error) {
|
||||
|
@ -144,17 +163,35 @@ func mockQueryNodeCreator(ctx context.Context, address string) (types.QueryNode,
|
|||
}
|
||||
|
||||
type mockQuery struct {
|
||||
isvalid bool
|
||||
mu sync.Mutex
|
||||
queryset map[UniqueID][]string
|
||||
failset map[UniqueID]error
|
||||
}
|
||||
|
||||
func (m *mockQuery) query(nodeID UniqueID, qn types.QueryNode) error {
|
||||
if nodeID == -1 {
|
||||
return fmt.Errorf("error at condition")
|
||||
func (m *mockQuery) query(_ context.Context, nodeID UniqueID, qn types.QueryNode, chs []string) error {
|
||||
m.mu.Lock()
|
||||
defer m.mu.Unlock()
|
||||
if err, ok := m.failset[nodeID]; ok {
|
||||
return err
|
||||
}
|
||||
|
||||
if m.isvalid {
|
||||
return nil
|
||||
}
|
||||
|
||||
return fmt.Errorf("mock error in query, NodeID=%d", nodeID)
|
||||
m.queryset[nodeID] = append(m.queryset[nodeID], chs...)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *mockQuery) init() {
|
||||
m.mu.Lock()
|
||||
defer m.mu.Unlock()
|
||||
m.queryset = make(map[int64][]string)
|
||||
m.failset = make(map[int64]error)
|
||||
}
|
||||
|
||||
func (m *mockQuery) records() map[UniqueID][]string {
|
||||
m.mu.Lock()
|
||||
defer m.mu.Unlock()
|
||||
for nodeID := range m.queryset {
|
||||
sort.Slice(m.queryset[nodeID], func(i, j int) bool {
|
||||
return m.queryset[nodeID][i] < m.queryset[nodeID][j]
|
||||
})
|
||||
}
|
||||
return m.queryset
|
||||
}
|
||||
|
|
|
@ -6,13 +6,11 @@ import (
|
|||
"fmt"
|
||||
"strconv"
|
||||
"strings"
|
||||
"sync"
|
||||
|
||||
"github.com/milvus-io/milvus/internal/parser/planparserv2"
|
||||
|
||||
"github.com/golang/protobuf/proto"
|
||||
"go.uber.org/zap"
|
||||
"golang.org/x/sync/errgroup"
|
||||
|
||||
"github.com/milvus-io/milvus/internal/log"
|
||||
"github.com/milvus-io/milvus/internal/metrics"
|
||||
|
@ -48,8 +46,6 @@ type queryTask struct {
|
|||
|
||||
resultBuf chan *internalpb.RetrieveResults
|
||||
toReduceResults []*internalpb.RetrieveResults
|
||||
runningGroup *errgroup.Group
|
||||
runningGroupCtx context.Context
|
||||
|
||||
queryShardPolicy pickShardPolicy
|
||||
shardMgr *shardClientMgr
|
||||
|
@ -92,7 +88,7 @@ func translateToOutputFieldIDs(outputFields []string, schema *schemapb.Collectio
|
|||
|
||||
func (t *queryTask) PreExecute(ctx context.Context) error {
|
||||
if t.queryShardPolicy == nil {
|
||||
t.queryShardPolicy = roundRobinPolicy
|
||||
t.queryShardPolicy = mergeRoundRobinPolicy
|
||||
}
|
||||
|
||||
t.Base.MsgType = commonpb.MsgType_Retrieve
|
||||
|
@ -228,28 +224,11 @@ func (t *queryTask) Execute(ctx context.Context) error {
|
|||
}
|
||||
t.resultBuf = make(chan *internalpb.RetrieveResults, len(shards))
|
||||
t.toReduceResults = make([]*internalpb.RetrieveResults, 0, len(shards))
|
||||
t.runningGroup, t.runningGroupCtx = errgroup.WithContext(ctx)
|
||||
for channelID, leaders := range shards {
|
||||
channelID := channelID
|
||||
leaders := leaders
|
||||
t.runningGroup.Go(func() error {
|
||||
log.Debug("proxy starting to query one shard",
|
||||
zap.Int64("msgID", t.ID()),
|
||||
zap.Int64("collectionID", t.CollectionID),
|
||||
zap.String("collection name", t.collectionName),
|
||||
zap.String("shard channel", channelID),
|
||||
zap.Uint64("timeoutTs", t.TimeoutTimestamp))
|
||||
|
||||
err := t.queryShard(t.runningGroupCtx, leaders, channelID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
})
|
||||
if err := t.queryShardPolicy(ctx, t.shardMgr, t.queryShard, shards); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
err = t.runningGroup.Wait()
|
||||
return err
|
||||
return nil
|
||||
}
|
||||
|
||||
err := executeQuery(WithCache)
|
||||
|
@ -274,28 +253,19 @@ func (t *queryTask) PostExecute(ctx context.Context) error {
|
|||
}()
|
||||
|
||||
var err error
|
||||
wg := sync.WaitGroup{}
|
||||
wg.Add(1)
|
||||
go func() {
|
||||
for {
|
||||
select {
|
||||
case <-t.TraceCtx().Done():
|
||||
log.Warn("proxy", zap.Int64("Query: wait to finish failed, timeout!, msgID:", t.ID()))
|
||||
return
|
||||
case <-t.runningGroupCtx.Done():
|
||||
log.Debug("all queries are finished or canceled", zap.Int64("msgID", t.ID()))
|
||||
close(t.resultBuf)
|
||||
for res := range t.resultBuf {
|
||||
t.toReduceResults = append(t.toReduceResults, res)
|
||||
log.Debug("proxy receives one query result", zap.Int64("sourceID", res.GetBase().GetSourceID()), zap.Any("msgID", t.ID()))
|
||||
}
|
||||
wg.Done()
|
||||
return
|
||||
}
|
||||
}
|
||||
}()
|
||||
|
||||
wg.Wait()
|
||||
select {
|
||||
case <-t.TraceCtx().Done():
|
||||
log.Warn("proxy", zap.Int64("Query: wait to finish failed, timeout!, msgID:", t.ID()))
|
||||
return nil
|
||||
default:
|
||||
log.Debug("all queries are finished or canceled", zap.Int64("msgID", t.ID()))
|
||||
close(t.resultBuf)
|
||||
for res := range t.resultBuf {
|
||||
t.toReduceResults = append(t.toReduceResults, res)
|
||||
log.Debug("proxy receives one query result", zap.Int64("sourceID", res.GetBase().GetSourceID()), zap.Any("msgID", t.ID()))
|
||||
}
|
||||
}
|
||||
|
||||
metrics.ProxyDecodeResultLatency.WithLabelValues(strconv.FormatInt(Params.ProxyCfg.GetNodeID(), 10), metrics.QueryLabel).Observe(0.0)
|
||||
tr.Record("reduceResultStart")
|
||||
|
@ -336,44 +306,31 @@ func (t *queryTask) PostExecute(ctx context.Context) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
func (t *queryTask) queryShard(ctx context.Context, leaders []nodeInfo, channelID string) error {
|
||||
query := func(nodeID UniqueID, qn types.QueryNode) error {
|
||||
req := &querypb.QueryRequest{
|
||||
Req: t.RetrieveRequest,
|
||||
DmlChannel: channelID,
|
||||
Scope: querypb.DataScope_All,
|
||||
}
|
||||
|
||||
result, err := qn.Query(ctx, req)
|
||||
if err != nil {
|
||||
log.Warn("QueryNode query return error", zap.Int64("msgID", t.ID()),
|
||||
zap.Int64("nodeID", nodeID), zap.String("channel", channelID), zap.Error(err))
|
||||
return err
|
||||
}
|
||||
if result.GetStatus().GetErrorCode() == commonpb.ErrorCode_NotShardLeader {
|
||||
log.Warn("QueryNode is not shardLeader", zap.Int64("msgID", t.ID()),
|
||||
zap.Int64("nodeID", nodeID), zap.String("channel", channelID))
|
||||
return errInvalidShardLeaders
|
||||
}
|
||||
if result.GetStatus().GetErrorCode() != commonpb.ErrorCode_Success {
|
||||
log.Warn("QueryNode query result error", zap.Int64("msgID", t.ID()),
|
||||
zap.Int64("nodeID", nodeID), zap.String("reason", result.GetStatus().GetReason()))
|
||||
return fmt.Errorf("fail to Query, QueryNode ID = %d, reason=%s", nodeID, result.GetStatus().GetReason())
|
||||
}
|
||||
|
||||
log.Debug("get query result", zap.Int64("msgID", t.ID()),
|
||||
zap.Int64("nodeID", nodeID), zap.String("channelID", channelID))
|
||||
t.resultBuf <- result
|
||||
return nil
|
||||
func (t *queryTask) queryShard(ctx context.Context, nodeID int64, qn types.QueryNode, channelIDs []string) error {
|
||||
req := &querypb.QueryRequest{
|
||||
Req: t.RetrieveRequest,
|
||||
DmlChannels: channelIDs,
|
||||
Scope: querypb.DataScope_All,
|
||||
}
|
||||
|
||||
err := t.queryShardPolicy(t.TraceCtx(), t.shardMgr, query, leaders)
|
||||
result, err := qn.Query(ctx, req)
|
||||
if err != nil {
|
||||
log.Warn("fail to Query to all shard leaders", zap.Int64("msgID", t.ID()),
|
||||
zap.Int64("taskID", t.ID()), zap.Any("shard leaders", leaders))
|
||||
log.Warn("QueryNode query return error", zap.Int64("msgID", t.ID()),
|
||||
zap.Int64("nodeID", nodeID), zap.Strings("channels", channelIDs), zap.Error(err))
|
||||
return err
|
||||
}
|
||||
if result.GetStatus().GetErrorCode() == commonpb.ErrorCode_NotShardLeader {
|
||||
log.Warn("QueryNode is not shardLeader", zap.Int64("nodeID", nodeID), zap.Strings("channels", channelIDs))
|
||||
return errInvalidShardLeaders
|
||||
}
|
||||
if result.GetStatus().GetErrorCode() != commonpb.ErrorCode_Success {
|
||||
log.Warn("QueryNode query result error", zap.Int64("msgID", t.ID()), zap.Int64("nodeID", nodeID),
|
||||
zap.String("reason", result.GetStatus().GetReason()))
|
||||
return fmt.Errorf("fail to Query, QueryNode ID = %d, reason=%s", nodeID, result.GetStatus().GetReason())
|
||||
}
|
||||
|
||||
log.Debug("get query result", zap.Int64("msgID", t.ID()), zap.Int64("nodeID", nodeID), zap.Strings("channelIDs", channelIDs))
|
||||
t.resultBuf <- result
|
||||
return nil
|
||||
}
|
||||
|
||||
|
|
|
@ -39,6 +39,10 @@ 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 {
|
||||
return fmt.Errorf("fake error")
|
||||
}
|
||||
)
|
||||
|
||||
mockCreator := func(ctx context.Context, address string) (types.QueryNode, error) {
|
||||
|
@ -125,10 +129,8 @@ func TestQueryTask_all(t *testing.T) {
|
|||
CollectionName: collectionName,
|
||||
Expr: expr,
|
||||
},
|
||||
qc: qc,
|
||||
|
||||
queryShardPolicy: roundRobinPolicy,
|
||||
shardMgr: mgr,
|
||||
qc: qc,
|
||||
shardMgr: mgr,
|
||||
}
|
||||
|
||||
assert.NoError(t, task.OnEnqueue())
|
||||
|
@ -143,6 +145,11 @@ func TestQueryTask_all(t *testing.T) {
|
|||
// after preExecute
|
||||
assert.Greater(t, task.TimeoutTimestamp, typeutil.ZeroTimestamp)
|
||||
|
||||
task.ctx = ctx
|
||||
task.queryShardPolicy = errPolicy
|
||||
assert.Error(t, task.Execute(ctx))
|
||||
|
||||
task.queryShardPolicy = mergeRoundRobinPolicy
|
||||
result1 := &internalpb.RetrieveResults{
|
||||
Base: &commonpb.MsgBase{MsgType: commonpb.MsgType_RetrieveResult},
|
||||
Status: &commonpb.Status{
|
||||
|
@ -164,9 +171,27 @@ func TestQueryTask_all(t *testing.T) {
|
|||
result1.FieldsData = append(result1.FieldsData, generateFieldData(dataType, fieldName, hitNum))
|
||||
}
|
||||
|
||||
task.ctx = ctx
|
||||
qn.queryError = fmt.Errorf("mock error")
|
||||
assert.Error(t, task.Execute(ctx))
|
||||
|
||||
qn.queryError = nil
|
||||
qn.withQueryResult = &internalpb.RetrieveResults{
|
||||
Status: &commonpb.Status{
|
||||
ErrorCode: commonpb.ErrorCode_NotShardLeader,
|
||||
},
|
||||
}
|
||||
assert.Equal(t, task.Execute(ctx), errInvalidShardLeaders)
|
||||
|
||||
qn.withQueryResult = &internalpb.RetrieveResults{
|
||||
Status: &commonpb.Status{
|
||||
ErrorCode: commonpb.ErrorCode_UnexpectedError,
|
||||
},
|
||||
}
|
||||
assert.Error(t, task.Execute(ctx))
|
||||
|
||||
qn.withQueryResult = result1
|
||||
|
||||
task.ctx = ctx
|
||||
assert.NoError(t, task.Execute(ctx))
|
||||
|
||||
assert.NoError(t, task.PostExecute(ctx))
|
||||
|
|
|
@ -6,13 +6,11 @@ import (
|
|||
"fmt"
|
||||
"regexp"
|
||||
"strconv"
|
||||
"sync"
|
||||
|
||||
"github.com/milvus-io/milvus/internal/parser/planparserv2"
|
||||
|
||||
"github.com/golang/protobuf/proto"
|
||||
"go.uber.org/zap"
|
||||
"golang.org/x/sync/errgroup"
|
||||
|
||||
"github.com/milvus-io/milvus/internal/log"
|
||||
"github.com/milvus-io/milvus/internal/metrics"
|
||||
|
@ -48,8 +46,6 @@ type searchTask struct {
|
|||
|
||||
resultBuf chan *internalpb.SearchResults
|
||||
toReduceResults []*internalpb.SearchResults
|
||||
runningGroup *errgroup.Group
|
||||
runningGroupCtx context.Context
|
||||
|
||||
searchShardPolicy pickShardPolicy
|
||||
shardMgr *shardClientMgr
|
||||
|
@ -178,7 +174,7 @@ func (t *searchTask) PreExecute(ctx context.Context) error {
|
|||
defer sp.Finish()
|
||||
|
||||
if t.searchShardPolicy == nil {
|
||||
t.searchShardPolicy = roundRobinPolicy
|
||||
t.searchShardPolicy = mergeRoundRobinPolicy
|
||||
}
|
||||
|
||||
t.Base.MsgType = commonpb.MsgType_Search
|
||||
|
@ -307,25 +303,11 @@ func (t *searchTask) Execute(ctx context.Context) error {
|
|||
}
|
||||
t.resultBuf = make(chan *internalpb.SearchResults, len(shard2Leaders))
|
||||
t.toReduceResults = make([]*internalpb.SearchResults, 0, len(shard2Leaders))
|
||||
t.runningGroup, t.runningGroupCtx = errgroup.WithContext(ctx)
|
||||
|
||||
// TODO: try to merge rpc send to different shard leaders.
|
||||
// If two shard leader is on the same querynode maybe we should merge request to save rpc
|
||||
for channelID, leaders := range shard2Leaders {
|
||||
channelID := channelID
|
||||
leaders := leaders
|
||||
t.runningGroup.Go(func() error {
|
||||
log.Debug("proxy starting to query one shard", zap.Int64("msgID", t.ID()),
|
||||
zap.Int64("collectionID", t.CollectionID),
|
||||
zap.String("collection name", t.collectionName),
|
||||
zap.String("shard channel", channelID),
|
||||
zap.Uint64("timeoutTs", t.TimeoutTimestamp))
|
||||
|
||||
return t.searchShard(t.runningGroupCtx, leaders, channelID)
|
||||
})
|
||||
if err := t.searchShardPolicy(ctx, t.shardMgr, t.searchShard, shard2Leaders); err != nil {
|
||||
log.Warn("failed to do search", zap.Error(err), zap.String("Shards", fmt.Sprintf("%v", shard2Leaders)))
|
||||
return err
|
||||
}
|
||||
err = t.runningGroup.Wait()
|
||||
return err
|
||||
return nil
|
||||
}
|
||||
|
||||
err := executeSearch(WithCache)
|
||||
|
@ -335,7 +317,7 @@ func (t *searchTask) Execute(ctx context.Context) error {
|
|||
return executeSearch(WithoutCache)
|
||||
}
|
||||
if err != nil {
|
||||
return fmt.Errorf("fail to search on all shard leaders, err=%w", err)
|
||||
return fmt.Errorf("fail to search on all shard leaders, err=%v", err)
|
||||
}
|
||||
|
||||
log.Debug("Search Execute done.", zap.Int64("msgID", t.ID()))
|
||||
|
@ -350,28 +332,19 @@ func (t *searchTask) PostExecute(ctx context.Context) error {
|
|||
tr.Elapse("done")
|
||||
}()
|
||||
|
||||
wg := sync.WaitGroup{}
|
||||
wg.Add(1)
|
||||
go func() {
|
||||
for {
|
||||
select {
|
||||
case <-t.TraceCtx().Done():
|
||||
log.Debug("wait to finish timeout!", zap.Int64("msgID", t.ID()))
|
||||
return
|
||||
case <-t.runningGroupCtx.Done():
|
||||
log.Debug("all searches are finished or canceled", zap.Int64("msgID", t.ID()))
|
||||
close(t.resultBuf)
|
||||
for res := range t.resultBuf {
|
||||
t.toReduceResults = append(t.toReduceResults, res)
|
||||
log.Debug("proxy receives one query result", zap.Int64("sourceID", res.GetBase().GetSourceID()), zap.Int64("msgID", t.ID()))
|
||||
}
|
||||
wg.Done()
|
||||
return
|
||||
}
|
||||
select {
|
||||
// in case timeout happened
|
||||
case <-t.TraceCtx().Done():
|
||||
log.Debug("wait to finish timeout!", zap.Int64("msgID", t.ID()))
|
||||
return nil
|
||||
default:
|
||||
log.Debug("all searches are finished or canceled", zap.Int64("msgID", t.ID()))
|
||||
close(t.resultBuf)
|
||||
for res := range t.resultBuf {
|
||||
t.toReduceResults = append(t.toReduceResults, res)
|
||||
log.Debug("proxy receives one query result", zap.Int64("sourceID", res.GetBase().GetSourceID()), zap.Int64("msgID", t.ID()))
|
||||
}
|
||||
}()
|
||||
|
||||
wg.Wait()
|
||||
}
|
||||
tr.Record("decodeResultStart")
|
||||
validSearchResults, err := decodeSearchResults(t.toReduceResults)
|
||||
if err != nil {
|
||||
|
@ -434,40 +407,29 @@ func (t *searchTask) PostExecute(ctx context.Context) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
func (t *searchTask) searchShard(ctx context.Context, leaders []nodeInfo, channelID string) error {
|
||||
|
||||
search := func(nodeID UniqueID, qn types.QueryNode) error {
|
||||
req := &querypb.SearchRequest{
|
||||
Req: t.SearchRequest,
|
||||
DmlChannel: channelID,
|
||||
Scope: querypb.DataScope_All,
|
||||
}
|
||||
result, err := qn.Search(ctx, req)
|
||||
if err != nil {
|
||||
log.Warn("QueryNode search return error", zap.Int64("msgID", t.ID()),
|
||||
zap.Int64("nodeID", nodeID), zap.String("channel", channelID), zap.Error(err))
|
||||
return err
|
||||
}
|
||||
if result.GetStatus().GetErrorCode() == commonpb.ErrorCode_NotShardLeader {
|
||||
log.Warn("QueryNode is not shardLeader", zap.Int64("msgID", t.ID()),
|
||||
zap.Int64("nodeID", nodeID), zap.String("channel", channelID))
|
||||
return errInvalidShardLeaders
|
||||
}
|
||||
if result.GetStatus().GetErrorCode() != commonpb.ErrorCode_Success {
|
||||
log.Warn("QueryNode search result error", zap.Int64("msgID", t.ID()),
|
||||
zap.Int64("nodeID", nodeID), zap.String("reason", result.GetStatus().GetReason()))
|
||||
return fmt.Errorf("fail to Search, QueryNode ID=%d, reason=%s", nodeID, result.GetStatus().GetReason())
|
||||
}
|
||||
t.resultBuf <- result
|
||||
return nil
|
||||
func (t *searchTask) searchShard(ctx context.Context, nodeID int64, qn types.QueryNode, channelIDs []string) error {
|
||||
req := &querypb.SearchRequest{
|
||||
Req: t.SearchRequest,
|
||||
DmlChannels: channelIDs,
|
||||
Scope: querypb.DataScope_All,
|
||||
}
|
||||
|
||||
err := t.searchShardPolicy(t.TraceCtx(), t.shardMgr, search, leaders)
|
||||
result, err := qn.Search(ctx, req)
|
||||
if err != nil {
|
||||
log.Warn("fail to search to all shard leaders", zap.Int64("msgID", t.ID()),
|
||||
zap.Any("shard leaders", leaders))
|
||||
log.Warn("QueryNode search return error", zap.Int64("msgID", t.ID()),
|
||||
zap.Int64("nodeID", nodeID), zap.Strings("channels", channelIDs), zap.Error(err))
|
||||
return err
|
||||
}
|
||||
if result.GetStatus().GetErrorCode() == commonpb.ErrorCode_NotShardLeader {
|
||||
log.Warn("QueryNode is not shardLeader", zap.Int64("msgID", t.ID()),
|
||||
zap.Int64("nodeID", nodeID), zap.Strings("channels", channelIDs))
|
||||
return errInvalidShardLeaders
|
||||
}
|
||||
if result.GetStatus().GetErrorCode() != commonpb.ErrorCode_Success {
|
||||
log.Warn("QueryNode search result error", zap.Int64("msgID", t.ID()), zap.Int64("nodeID", nodeID),
|
||||
zap.String("reason", result.GetStatus().GetReason()))
|
||||
return fmt.Errorf("fail to Search, QueryNode ID=%d, reason=%s", nodeID, result.GetStatus().GetReason())
|
||||
}
|
||||
t.resultBuf <- result
|
||||
|
||||
return nil
|
||||
}
|
||||
|
|
|
@ -3,6 +3,7 @@ package proxy
|
|||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
|
@ -10,6 +11,7 @@ import (
|
|||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
"github.com/milvus-io/milvus/internal/common"
|
||||
"github.com/milvus-io/milvus/internal/types"
|
||||
|
||||
"github.com/milvus-io/milvus/internal/proto/commonpb"
|
||||
|
@ -52,10 +54,6 @@ func TestSearchTask_PostExecute(t *testing.T) {
|
|||
// no result
|
||||
qt.resultBuf <- &internalpb.SearchResults{}
|
||||
|
||||
mockctx, mockcancel := context.WithCancel(ctx)
|
||||
qt.runningGroupCtx = mockctx
|
||||
mockcancel()
|
||||
|
||||
err := qt.PostExecute(context.TODO())
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, qt.result.Status.ErrorCode, commonpb.ErrorCode_Success)
|
||||
|
@ -1591,3 +1589,148 @@ func Test_checkIfLoaded(t *testing.T) {
|
|||
assert.False(t, loaded)
|
||||
})
|
||||
}
|
||||
|
||||
func TestSearchTask_ErrExecute(t *testing.T) {
|
||||
Params.Init()
|
||||
|
||||
var (
|
||||
err error
|
||||
ctx = context.TODO()
|
||||
|
||||
rc = NewRootCoordMock()
|
||||
qc = NewQueryCoordMock(withValidShardLeaders())
|
||||
qn = &QueryNodeMock{}
|
||||
|
||||
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 {
|
||||
return fmt.Errorf("fake error")
|
||||
}
|
||||
)
|
||||
|
||||
mockCreator := func(ctx context.Context, address string) (types.QueryNode, error) {
|
||||
return qn, nil
|
||||
}
|
||||
|
||||
mgr := newShardClientMgr(withShardClientCreator(mockCreator))
|
||||
|
||||
rc.Start()
|
||||
defer rc.Stop()
|
||||
qc.Start()
|
||||
defer qc.Stop()
|
||||
|
||||
err = InitMetaCache(rc, qc, mgr)
|
||||
assert.NoError(t, err)
|
||||
|
||||
fieldName2Types := map[string]schemapb.DataType{
|
||||
testBoolField: schemapb.DataType_Bool,
|
||||
testInt32Field: schemapb.DataType_Int32,
|
||||
testInt64Field: schemapb.DataType_Int64,
|
||||
testFloatField: schemapb.DataType_Float,
|
||||
testDoubleField: schemapb.DataType_Double,
|
||||
testFloatVecField: schemapb.DataType_FloatVector,
|
||||
}
|
||||
if enableMultipleVectorFields {
|
||||
fieldName2Types[testBinaryVecField] = schemapb.DataType_BinaryVector
|
||||
}
|
||||
|
||||
schema := constructCollectionSchemaByDataType(collectionName, fieldName2Types, testInt64Field, false)
|
||||
marshaledSchema, err := proto.Marshal(schema)
|
||||
assert.NoError(t, err)
|
||||
|
||||
createColT := &createCollectionTask{
|
||||
Condition: NewTaskCondition(ctx),
|
||||
CreateCollectionRequest: &milvuspb.CreateCollectionRequest{
|
||||
CollectionName: collectionName,
|
||||
Schema: marshaledSchema,
|
||||
ShardsNum: shardsNum,
|
||||
},
|
||||
ctx: ctx,
|
||||
rootCoord: rc,
|
||||
}
|
||||
|
||||
require.NoError(t, createColT.OnEnqueue())
|
||||
require.NoError(t, createColT.PreExecute(ctx))
|
||||
require.NoError(t, createColT.Execute(ctx))
|
||||
require.NoError(t, createColT.PostExecute(ctx))
|
||||
|
||||
collectionID, err := globalMetaCache.GetCollectionID(ctx, collectionName)
|
||||
assert.NoError(t, err)
|
||||
|
||||
status, err := qc.LoadCollection(ctx, &querypb.LoadCollectionRequest{
|
||||
Base: &commonpb.MsgBase{
|
||||
MsgType: commonpb.MsgType_LoadCollection,
|
||||
SourceID: Params.ProxyCfg.GetNodeID(),
|
||||
},
|
||||
CollectionID: collectionID,
|
||||
})
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, commonpb.ErrorCode_Success, status.ErrorCode)
|
||||
|
||||
// test begins
|
||||
task := &searchTask{
|
||||
Condition: NewTaskCondition(ctx),
|
||||
SearchRequest: &internalpb.SearchRequest{
|
||||
Base: &commonpb.MsgBase{
|
||||
MsgType: commonpb.MsgType_Retrieve,
|
||||
SourceID: Params.ProxyCfg.GetNodeID(),
|
||||
},
|
||||
CollectionID: collectionID,
|
||||
OutputFieldsId: make([]int64, len(fieldName2Types)),
|
||||
},
|
||||
ctx: ctx,
|
||||
result: &milvuspb.SearchResults{
|
||||
Status: &commonpb.Status{
|
||||
ErrorCode: commonpb.ErrorCode_Success,
|
||||
},
|
||||
},
|
||||
request: &milvuspb.SearchRequest{
|
||||
Base: &commonpb.MsgBase{
|
||||
MsgType: commonpb.MsgType_Retrieve,
|
||||
SourceID: Params.ProxyCfg.GetNodeID(),
|
||||
},
|
||||
CollectionName: collectionName,
|
||||
},
|
||||
qc: qc,
|
||||
shardMgr: mgr,
|
||||
}
|
||||
for i := 0; i < len(fieldName2Types); i++ {
|
||||
task.SearchRequest.OutputFieldsId[i] = int64(common.StartOfUserFieldID + i)
|
||||
}
|
||||
|
||||
assert.NoError(t, task.OnEnqueue())
|
||||
|
||||
task.ctx = ctx
|
||||
|
||||
assert.NoError(t, task.PreExecute(ctx))
|
||||
|
||||
task.searchShardPolicy = errPolicy
|
||||
assert.Error(t, task.Execute(ctx))
|
||||
|
||||
task.searchShardPolicy = mergeRoundRobinPolicy
|
||||
qn.searchError = fmt.Errorf("mock error")
|
||||
assert.Error(t, task.Execute(ctx))
|
||||
|
||||
qn.searchError = nil
|
||||
qn.withSearchResult = &internalpb.SearchResults{
|
||||
Status: &commonpb.Status{
|
||||
ErrorCode: commonpb.ErrorCode_NotShardLeader,
|
||||
},
|
||||
}
|
||||
assert.Equal(t, task.Execute(ctx), errInvalidShardLeaders)
|
||||
|
||||
qn.withSearchResult = &internalpb.SearchResults{
|
||||
Status: &commonpb.Status{
|
||||
ErrorCode: commonpb.ErrorCode_UnexpectedError,
|
||||
},
|
||||
}
|
||||
assert.Error(t, task.Execute(ctx))
|
||||
|
||||
result1 := &internalpb.SearchResults{
|
||||
Status: &commonpb.Status{
|
||||
ErrorCode: commonpb.ErrorCode_Success,
|
||||
},
|
||||
}
|
||||
qn.withSearchResult = result1
|
||||
assert.NoError(t, task.Execute(ctx))
|
||||
}
|
||||
|
|
|
@ -76,7 +76,7 @@ func benchmarkQueryCollectionSearch(nq int64, b *testing.B) {
|
|||
iReq, _ := genSearchRequest(nq, IndexFaissIDMap, collection.schema)
|
||||
queryReq := &queryPb.SearchRequest{
|
||||
Req: iReq,
|
||||
DmlChannel: defaultDMLChannel,
|
||||
DmlChannels: []string{defaultDMLChannel},
|
||||
SegmentIDs: []UniqueID{defaultSegmentID},
|
||||
FromShardLeader: true,
|
||||
Scope: queryPb.DataScope_Historical,
|
||||
|
|
|
@ -19,8 +19,10 @@ package querynode
|
|||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"sync"
|
||||
|
||||
"go.uber.org/zap"
|
||||
"golang.org/x/sync/errgroup"
|
||||
|
||||
"github.com/milvus-io/milvus/internal/common"
|
||||
"github.com/milvus-io/milvus/internal/log"
|
||||
|
@ -433,6 +435,61 @@ func (node *QueryNode) isHealthy() bool {
|
|||
|
||||
// Search performs replica search tasks.
|
||||
func (node *QueryNode) Search(ctx context.Context, req *queryPb.SearchRequest) (*internalpb.SearchResults, error) {
|
||||
log.Debug("Received SearchRequest",
|
||||
zap.Int64("msgID", req.GetReq().GetBase().GetMsgID()),
|
||||
zap.Strings("vChannels", req.GetDmlChannels()),
|
||||
zap.Int64s("segmentIDs", req.GetSegmentIDs()),
|
||||
zap.Uint64("guaranteeTimestamp", req.GetReq().GetGuaranteeTimestamp()),
|
||||
zap.Uint64("timeTravel", req.GetReq().GetTravelTimestamp()))
|
||||
|
||||
failRet := &internalpb.SearchResults{
|
||||
Status: &commonpb.Status{
|
||||
ErrorCode: commonpb.ErrorCode_Success,
|
||||
},
|
||||
}
|
||||
toReduceResults := make([]*internalpb.SearchResults, 0)
|
||||
runningGp, runningCtx := errgroup.WithContext(ctx)
|
||||
mu := &sync.Mutex{}
|
||||
for _, ch := range req.GetDmlChannels() {
|
||||
ch := ch
|
||||
req := &querypb.SearchRequest{
|
||||
Req: req.Req,
|
||||
DmlChannels: []string{ch},
|
||||
SegmentIDs: req.SegmentIDs,
|
||||
FromShardLeader: req.FromShardLeader,
|
||||
Scope: req.Scope,
|
||||
}
|
||||
runningGp.Go(func() error {
|
||||
ret, err := node.searchWithDmlChannel(runningCtx, req, ch)
|
||||
mu.Lock()
|
||||
defer mu.Unlock()
|
||||
if err != nil {
|
||||
failRet.Status.Reason = err.Error()
|
||||
failRet.Status.ErrorCode = commonpb.ErrorCode_UnexpectedError
|
||||
return err
|
||||
}
|
||||
if ret.GetStatus().GetErrorCode() != commonpb.ErrorCode_Success {
|
||||
failRet.Status.Reason = ret.Status.Reason
|
||||
failRet.Status.ErrorCode = ret.Status.ErrorCode
|
||||
return fmt.Errorf("%s", ret.Status.Reason)
|
||||
}
|
||||
toReduceResults = append(toReduceResults, ret)
|
||||
return nil
|
||||
})
|
||||
}
|
||||
if err := runningGp.Wait(); err != nil {
|
||||
return failRet, nil
|
||||
}
|
||||
ret, err := reduceSearchResults(toReduceResults, req.Req.GetNq(), req.Req.GetTopk(), req.Req.GetMetricType())
|
||||
if err != nil {
|
||||
failRet.Status.ErrorCode = commonpb.ErrorCode_UnexpectedError
|
||||
failRet.Status.Reason = err.Error()
|
||||
return failRet, nil
|
||||
}
|
||||
return ret, nil
|
||||
}
|
||||
|
||||
func (node *QueryNode) searchWithDmlChannel(ctx context.Context, req *queryPb.SearchRequest, dmlChannel string) (*internalpb.SearchResults, error) {
|
||||
metrics.QueryNodeSQCount.WithLabelValues(fmt.Sprint(Params.QueryNodeCfg.GetNodeID()), metrics.SearchLabel, metrics.TotalLabel).Inc()
|
||||
failRet := &internalpb.SearchResults{
|
||||
Status: &commonpb.Status{
|
||||
|
@ -454,7 +511,7 @@ func (node *QueryNode) Search(ctx context.Context, req *queryPb.SearchRequest) (
|
|||
log.Debug("Received SearchRequest",
|
||||
zap.Int64("msgID", msgID),
|
||||
zap.Bool("fromShardLeader", req.GetFromShardLeader()),
|
||||
zap.String("vChannel", req.GetDmlChannel()),
|
||||
zap.String("vChannel", dmlChannel),
|
||||
zap.Int64s("segmentIDs", req.GetSegmentIDs()),
|
||||
zap.Uint64("guaranteeTimestamp", req.GetReq().GetGuaranteeTimestamp()),
|
||||
zap.Uint64("timeTravel", req.GetReq().GetTravelTimestamp()))
|
||||
|
@ -464,11 +521,11 @@ func (node *QueryNode) Search(ctx context.Context, req *queryPb.SearchRequest) (
|
|||
return failRet, nil
|
||||
}
|
||||
|
||||
qs, err := node.queryShardService.getQueryShard(req.GetDmlChannel())
|
||||
qs, err := node.queryShardService.getQueryShard(dmlChannel)
|
||||
if err != nil {
|
||||
log.Warn("Search failed, failed to get query shard",
|
||||
zap.Int64("msgID", msgID),
|
||||
zap.String("dml channel", req.GetDmlChannel()),
|
||||
zap.String("dml channel", dmlChannel),
|
||||
zap.Error(err))
|
||||
failRet.Status.ErrorCode = commonpb.ErrorCode_NotShardLeader
|
||||
failRet.Status.Reason = err.Error()
|
||||
|
@ -478,7 +535,7 @@ func (node *QueryNode) Search(ctx context.Context, req *queryPb.SearchRequest) (
|
|||
log.Debug("start do search",
|
||||
zap.Int64("msgID", msgID),
|
||||
zap.Bool("fromShardLeader", req.GetFromShardLeader()),
|
||||
zap.String("vChannel", req.GetDmlChannel()),
|
||||
zap.String("vChannel", dmlChannel),
|
||||
zap.Int64s("segmentIDs", req.GetSegmentIDs()))
|
||||
tr := timerecord.NewTimeRecorder("")
|
||||
|
||||
|
@ -503,7 +560,7 @@ func (node *QueryNode) Search(ctx context.Context, req *queryPb.SearchRequest) (
|
|||
}
|
||||
|
||||
tr.Elapse(fmt.Sprintf("do search done, msgID = %d, fromSharedLeader = %t, vChannel = %s, segmentIDs = %v",
|
||||
msgID, req.GetFromShardLeader(), req.GetDmlChannel(), req.GetSegmentIDs()))
|
||||
msgID, req.GetFromShardLeader(), dmlChannel, req.GetSegmentIDs()))
|
||||
|
||||
failRet.Status.ErrorCode = commonpb.ErrorCode_Success
|
||||
metrics.QueryNodeSQLatencyInQueue.WithLabelValues(fmt.Sprint(Params.QueryNodeCfg.GetNodeID()),
|
||||
|
@ -517,10 +574,10 @@ func (node *QueryNode) Search(ctx context.Context, req *queryPb.SearchRequest) (
|
|||
}
|
||||
|
||||
//from Proxy
|
||||
cluster, ok := qs.clusterService.getShardCluster(req.GetDmlChannel())
|
||||
cluster, ok := qs.clusterService.getShardCluster(dmlChannel)
|
||||
if !ok {
|
||||
failRet.Status.ErrorCode = commonpb.ErrorCode_NotShardLeader
|
||||
failRet.Status.Reason = fmt.Sprintf("channel %s leader is not here", req.GetDmlChannel())
|
||||
failRet.Status.Reason = fmt.Sprintf("channel %s leader is not here", dmlChannel)
|
||||
return failRet, nil
|
||||
}
|
||||
|
||||
|
@ -563,7 +620,7 @@ func (node *QueryNode) Search(ctx context.Context, req *queryPb.SearchRequest) (
|
|||
}
|
||||
|
||||
tr.Elapse(fmt.Sprintf("start reduce search result, msgID = %d, fromSharedLeader = %t, vChannel = %s, segmentIDs = %v",
|
||||
msgID, req.GetFromShardLeader(), req.GetDmlChannel(), req.GetSegmentIDs()))
|
||||
msgID, req.GetFromShardLeader(), dmlChannel, req.GetSegmentIDs()))
|
||||
|
||||
results = append(results, streamingResult)
|
||||
ret, err2 := reduceSearchResults(results, req.Req.GetNq(), req.Req.GetTopk(), req.Req.GetMetricType())
|
||||
|
@ -573,7 +630,7 @@ func (node *QueryNode) Search(ctx context.Context, req *queryPb.SearchRequest) (
|
|||
}
|
||||
|
||||
tr.Elapse(fmt.Sprintf("do search done, msgID = %d, fromSharedLeader = %t, vChannel = %s, segmentIDs = %v",
|
||||
msgID, req.GetFromShardLeader(), req.GetDmlChannel(), req.GetSegmentIDs()))
|
||||
msgID, req.GetFromShardLeader(), dmlChannel, req.GetSegmentIDs()))
|
||||
|
||||
failRet.Status.ErrorCode = commonpb.ErrorCode_Success
|
||||
latency := tr.ElapseSpan()
|
||||
|
@ -584,8 +641,7 @@ func (node *QueryNode) Search(ctx context.Context, req *queryPb.SearchRequest) (
|
|||
return ret, nil
|
||||
}
|
||||
|
||||
// Query performs replica query tasks.
|
||||
func (node *QueryNode) Query(ctx context.Context, req *queryPb.QueryRequest) (*internalpb.RetrieveResults, error) {
|
||||
func (node *QueryNode) queryWithDmlChannel(ctx context.Context, req *queryPb.QueryRequest, dmlChannel string) (*internalpb.RetrieveResults, error) {
|
||||
metrics.QueryNodeSQCount.WithLabelValues(fmt.Sprint(Params.QueryNodeCfg.GetNodeID()), metrics.QueryLabel, metrics.TotalLabel).Inc()
|
||||
failRet := &internalpb.RetrieveResults{
|
||||
Status: &commonpb.Status{
|
||||
|
@ -607,7 +663,7 @@ func (node *QueryNode) Query(ctx context.Context, req *queryPb.QueryRequest) (*i
|
|||
log.Debug("Received QueryRequest",
|
||||
zap.Int64("msgID", msgID),
|
||||
zap.Bool("fromShardLeader", req.GetFromShardLeader()),
|
||||
zap.String("vChannel", req.GetDmlChannel()),
|
||||
zap.String("vChannel", dmlChannel),
|
||||
zap.Int64s("segmentIDs", req.GetSegmentIDs()),
|
||||
zap.Uint64("guaranteeTimestamp", req.GetReq().GetGuaranteeTimestamp()),
|
||||
zap.Uint64("timeTravel", req.GetReq().GetTravelTimestamp()))
|
||||
|
@ -617,9 +673,9 @@ func (node *QueryNode) Query(ctx context.Context, req *queryPb.QueryRequest) (*i
|
|||
return failRet, nil
|
||||
}
|
||||
|
||||
qs, err := node.queryShardService.getQueryShard(req.GetDmlChannel())
|
||||
qs, err := node.queryShardService.getQueryShard(dmlChannel)
|
||||
if err != nil {
|
||||
log.Warn("Query failed, failed to get query shard", zap.Int64("msgID", msgID), zap.String("dml channel", req.GetDmlChannel()), zap.Error(err))
|
||||
log.Warn("Query failed, failed to get query shard", zap.Int64("msgID", msgID), zap.String("dml channel", dmlChannel), zap.Error(err))
|
||||
failRet.Status.Reason = err.Error()
|
||||
return failRet, nil
|
||||
}
|
||||
|
@ -627,7 +683,7 @@ func (node *QueryNode) Query(ctx context.Context, req *queryPb.QueryRequest) (*i
|
|||
log.Debug("start do query",
|
||||
zap.Int64("msgID", msgID),
|
||||
zap.Bool("fromShardLeader", req.GetFromShardLeader()),
|
||||
zap.String("vChannel", req.GetDmlChannel()),
|
||||
zap.String("vChannel", dmlChannel),
|
||||
zap.Int64s("segmentIDs", req.GetSegmentIDs()))
|
||||
tr := timerecord.NewTimeRecorder("")
|
||||
|
||||
|
@ -649,7 +705,7 @@ func (node *QueryNode) Query(ctx context.Context, req *queryPb.QueryRequest) (*i
|
|||
}
|
||||
|
||||
tr.Elapse(fmt.Sprintf("do query done, msgID = %d, fromSharedLeader = %t, vChannel = %s, segmentIDs = %v",
|
||||
msgID, req.GetFromShardLeader(), req.GetDmlChannel(), req.GetSegmentIDs()))
|
||||
msgID, req.GetFromShardLeader(), dmlChannel, req.GetSegmentIDs()))
|
||||
|
||||
failRet.Status.ErrorCode = commonpb.ErrorCode_Success
|
||||
metrics.QueryNodeSQLatencyInQueue.WithLabelValues(fmt.Sprint(Params.QueryNodeCfg.GetNodeID()),
|
||||
|
@ -662,10 +718,10 @@ func (node *QueryNode) Query(ctx context.Context, req *queryPb.QueryRequest) (*i
|
|||
return queryTask.Ret, nil
|
||||
}
|
||||
|
||||
cluster, ok := qs.clusterService.getShardCluster(req.GetDmlChannel())
|
||||
cluster, ok := qs.clusterService.getShardCluster(dmlChannel)
|
||||
if !ok {
|
||||
failRet.Status.ErrorCode = commonpb.ErrorCode_NotShardLeader
|
||||
failRet.Status.Reason = fmt.Sprintf("channel %s leader is not here", req.GetDmlChannel())
|
||||
failRet.Status.Reason = fmt.Sprintf("channel %s leader is not here", dmlChannel)
|
||||
return failRet, nil
|
||||
}
|
||||
|
||||
|
@ -707,7 +763,7 @@ func (node *QueryNode) Query(ctx context.Context, req *queryPb.QueryRequest) (*i
|
|||
}
|
||||
|
||||
tr.Elapse(fmt.Sprintf("start reduce query result, msgID = %d, fromSharedLeader = %t, vChannel = %s, segmentIDs = %v",
|
||||
msgID, req.GetFromShardLeader(), req.GetDmlChannel(), req.GetSegmentIDs()))
|
||||
msgID, req.GetFromShardLeader(), dmlChannel, req.GetSegmentIDs()))
|
||||
|
||||
results = append(results, streamingResult)
|
||||
ret, err2 := mergeInternalRetrieveResults(results)
|
||||
|
@ -717,7 +773,7 @@ func (node *QueryNode) Query(ctx context.Context, req *queryPb.QueryRequest) (*i
|
|||
}
|
||||
|
||||
tr.Elapse(fmt.Sprintf("do query done, msgID = %d, fromSharedLeader = %t, vChannel = %s, segmentIDs = %v",
|
||||
msgID, req.GetFromShardLeader(), req.GetDmlChannel(), req.GetSegmentIDs()))
|
||||
msgID, req.GetFromShardLeader(), dmlChannel, req.GetSegmentIDs()))
|
||||
|
||||
failRet.Status.ErrorCode = commonpb.ErrorCode_Success
|
||||
latency := tr.ElapseSpan()
|
||||
|
@ -726,6 +782,63 @@ func (node *QueryNode) Query(ctx context.Context, req *queryPb.QueryRequest) (*i
|
|||
return ret, nil
|
||||
}
|
||||
|
||||
// Query performs replica query tasks.
|
||||
func (node *QueryNode) Query(ctx context.Context, req *querypb.QueryRequest) (*internalpb.RetrieveResults, error) {
|
||||
log.Debug("Received QueryRequest", zap.Int64("msgID", req.GetReq().GetBase().GetMsgID()),
|
||||
zap.Strings("vChannels", req.GetDmlChannels()),
|
||||
zap.Int64s("segmentIDs", req.GetSegmentIDs()),
|
||||
zap.Uint64("guaranteeTimestamp", req.Req.GetGuaranteeTimestamp()),
|
||||
zap.Uint64("timeTravel", req.GetReq().GetTravelTimestamp()))
|
||||
|
||||
failRet := &internalpb.RetrieveResults{
|
||||
Status: &commonpb.Status{
|
||||
ErrorCode: commonpb.ErrorCode_Success,
|
||||
},
|
||||
}
|
||||
|
||||
toMergeResults := make([]*internalpb.RetrieveResults, 0)
|
||||
runningGp, runningCtx := errgroup.WithContext(ctx)
|
||||
mu := &sync.Mutex{}
|
||||
|
||||
for _, ch := range req.GetDmlChannels() {
|
||||
ch := ch
|
||||
req := &querypb.QueryRequest{
|
||||
Req: req.Req,
|
||||
DmlChannels: []string{ch},
|
||||
SegmentIDs: req.SegmentIDs,
|
||||
FromShardLeader: req.FromShardLeader,
|
||||
Scope: req.Scope,
|
||||
}
|
||||
runningGp.Go(func() error {
|
||||
ret, err := node.queryWithDmlChannel(runningCtx, req, ch)
|
||||
mu.Lock()
|
||||
defer mu.Unlock()
|
||||
if err != nil {
|
||||
failRet.Status.Reason = err.Error()
|
||||
failRet.Status.ErrorCode = commonpb.ErrorCode_UnexpectedError
|
||||
return err
|
||||
}
|
||||
if ret.GetStatus().GetErrorCode() != commonpb.ErrorCode_Success {
|
||||
failRet.Status.Reason = ret.Status.Reason
|
||||
failRet.Status.ErrorCode = ret.Status.ErrorCode
|
||||
return fmt.Errorf("%s", ret.Status.Reason)
|
||||
}
|
||||
toMergeResults = append(toMergeResults, ret)
|
||||
return nil
|
||||
})
|
||||
}
|
||||
if err := runningGp.Wait(); err != nil {
|
||||
return failRet, nil
|
||||
}
|
||||
ret, err := mergeInternalRetrieveResults(toMergeResults)
|
||||
if err != nil {
|
||||
failRet.Status.ErrorCode = commonpb.ErrorCode_UnexpectedError
|
||||
failRet.Status.Reason = err.Error()
|
||||
return failRet, nil
|
||||
}
|
||||
return ret, nil
|
||||
}
|
||||
|
||||
// SyncReplicaSegments syncs replica node & segments states
|
||||
func (node *QueryNode) SyncReplicaSegments(ctx context.Context, req *querypb.SyncReplicaSegmentsRequest) (*commonpb.Status, error) {
|
||||
if !node.isHealthy() {
|
||||
|
|
|
@ -477,15 +477,61 @@ func TestImpl_Search(t *testing.T) {
|
|||
require.NoError(t, err)
|
||||
|
||||
node.queryShardService.addQueryShard(defaultCollectionID, defaultDMLChannel, defaultReplicaID)
|
||||
node.ShardClusterService.addShardCluster(defaultCollectionID, defaultReplicaID, defaultDMLChannel)
|
||||
// shard cluster not synced
|
||||
_, err = node.Search(ctx, &queryPb.SearchRequest{
|
||||
Req: req,
|
||||
FromShardLeader: false,
|
||||
DmlChannels: []string{defaultDMLChannel},
|
||||
})
|
||||
assert.NoError(t, err)
|
||||
|
||||
// shard cluster sync segments
|
||||
sc, ok := node.ShardClusterService.getShardCluster(defaultDMLChannel)
|
||||
assert.True(t, ok)
|
||||
sc.SyncSegments(nil, segmentStateLoaded)
|
||||
|
||||
_, err = node.Search(ctx, &queryPb.SearchRequest{
|
||||
Req: req,
|
||||
FromShardLeader: false,
|
||||
DmlChannel: defaultDMLChannel,
|
||||
DmlChannels: []string{defaultDMLChannel},
|
||||
})
|
||||
assert.NoError(t, err)
|
||||
}
|
||||
|
||||
func TestImpl_searchWithDmlChannel(t *testing.T) {
|
||||
ctx, cancel := context.WithCancel(context.Background())
|
||||
defer cancel()
|
||||
|
||||
node, err := genSimpleQueryNode(ctx)
|
||||
require.NoError(t, err)
|
||||
|
||||
schema := genTestCollectionSchema()
|
||||
req, err := genSearchRequest(defaultNQ, IndexFaissIDMap, schema)
|
||||
require.NoError(t, err)
|
||||
|
||||
node.queryShardService.addQueryShard(defaultCollectionID, defaultDMLChannel, defaultReplicaID)
|
||||
node.ShardClusterService.addShardCluster(defaultCollectionID, defaultReplicaID, defaultDMLChannel)
|
||||
sc, ok := node.ShardClusterService.getShardCluster(defaultDMLChannel)
|
||||
assert.True(t, ok)
|
||||
sc.SyncSegments(nil, segmentStateLoaded)
|
||||
|
||||
_, err = node.searchWithDmlChannel(ctx, &queryPb.SearchRequest{
|
||||
Req: req,
|
||||
FromShardLeader: false,
|
||||
DmlChannels: []string{defaultDMLChannel},
|
||||
}, defaultDMLChannel)
|
||||
assert.NoError(t, err)
|
||||
|
||||
// search for wrong dml channel
|
||||
_, err = node.searchWithDmlChannel(ctx, &queryPb.SearchRequest{
|
||||
Req: req,
|
||||
FromShardLeader: false,
|
||||
DmlChannels: []string{defaultDMLChannel + "_suffix"},
|
||||
}, defaultDMLChannel)
|
||||
assert.NoError(t, err)
|
||||
}
|
||||
|
||||
func TestImpl_Query(t *testing.T) {
|
||||
ctx, cancel := context.WithCancel(context.Background())
|
||||
defer cancel()
|
||||
|
@ -499,15 +545,62 @@ func TestImpl_Query(t *testing.T) {
|
|||
require.NoError(t, err)
|
||||
|
||||
node.queryShardService.addQueryShard(defaultCollectionID, defaultDMLChannel, defaultReplicaID)
|
||||
node.ShardClusterService.addShardCluster(defaultCollectionID, defaultReplicaID, defaultDMLChannel)
|
||||
// shard cluster not synced
|
||||
_, err = node.Query(ctx, &queryPb.QueryRequest{
|
||||
Req: req,
|
||||
FromShardLeader: false,
|
||||
DmlChannels: []string{defaultDMLChannel},
|
||||
})
|
||||
assert.NoError(t, err)
|
||||
|
||||
// sync cluster segments
|
||||
sc, ok := node.ShardClusterService.getShardCluster(defaultDMLChannel)
|
||||
assert.True(t, ok)
|
||||
sc.SyncSegments(nil, segmentStateLoaded)
|
||||
|
||||
_, err = node.Query(ctx, &queryPb.QueryRequest{
|
||||
Req: req,
|
||||
FromShardLeader: false,
|
||||
DmlChannel: defaultDMLChannel,
|
||||
DmlChannels: []string{defaultDMLChannel},
|
||||
})
|
||||
assert.NoError(t, err)
|
||||
}
|
||||
|
||||
func TestImpl_queryWithDmlChannel(t *testing.T) {
|
||||
ctx, cancel := context.WithCancel(context.Background())
|
||||
defer cancel()
|
||||
|
||||
node, err := genSimpleQueryNode(ctx)
|
||||
defer node.Stop()
|
||||
require.NoError(t, err)
|
||||
|
||||
schema := genTestCollectionSchema()
|
||||
req, err := genRetrieveRequest(schema)
|
||||
require.NoError(t, err)
|
||||
|
||||
node.queryShardService.addQueryShard(defaultCollectionID, defaultDMLChannel, defaultReplicaID)
|
||||
node.ShardClusterService.addShardCluster(defaultCollectionID, defaultReplicaID, defaultDMLChannel)
|
||||
sc, ok := node.ShardClusterService.getShardCluster(defaultDMLChannel)
|
||||
assert.True(t, ok)
|
||||
sc.SyncSegments(nil, segmentStateLoaded)
|
||||
|
||||
_, err = node.queryWithDmlChannel(ctx, &queryPb.QueryRequest{
|
||||
Req: req,
|
||||
FromShardLeader: false,
|
||||
DmlChannels: []string{defaultDMLChannel},
|
||||
}, defaultDMLChannel)
|
||||
assert.NoError(t, err)
|
||||
|
||||
// query for wrong dml channel
|
||||
_, err = node.queryWithDmlChannel(ctx, &queryPb.QueryRequest{
|
||||
Req: req,
|
||||
FromShardLeader: false,
|
||||
DmlChannels: []string{defaultDMLChannel + "_suffix"},
|
||||
}, defaultDMLChannel)
|
||||
assert.NoError(t, err)
|
||||
}
|
||||
|
||||
func TestImpl_SyncReplicaSegments(t *testing.T) {
|
||||
t.Run("QueryNode not healthy", func(t *testing.T) {
|
||||
ctx, cancel := context.WithCancel(context.Background())
|
||||
|
|
|
@ -1449,7 +1449,7 @@ func genSearchPlanAndRequests(collection *Collection, indexType string, nq int64
|
|||
iReq, _ := genSearchRequest(nq, indexType, collection.schema)
|
||||
queryReq := &querypb.SearchRequest{
|
||||
Req: iReq,
|
||||
DmlChannel: defaultDMLChannel,
|
||||
DmlChannels: []string{defaultDMLChannel},
|
||||
SegmentIDs: []UniqueID{defaultSegmentID},
|
||||
FromShardLeader: true,
|
||||
Scope: querypb.DataScope_Historical,
|
||||
|
|
|
@ -22,8 +22,6 @@ import (
|
|||
"fmt"
|
||||
"sync"
|
||||
|
||||
"github.com/golang/protobuf/proto"
|
||||
|
||||
"go.uber.org/atomic"
|
||||
"go.uber.org/zap"
|
||||
|
||||
|
@ -32,6 +30,7 @@ import (
|
|||
"github.com/milvus-io/milvus/internal/proto/internalpb"
|
||||
"github.com/milvus-io/milvus/internal/proto/querypb"
|
||||
"github.com/milvus-io/milvus/internal/util/errorutil"
|
||||
"github.com/milvus-io/milvus/internal/util/funcutil"
|
||||
"github.com/milvus-io/milvus/internal/util/typeutil"
|
||||
)
|
||||
|
||||
|
@ -724,9 +723,8 @@ func (sc *ShardCluster) Search(ctx context.Context, req *querypb.SearchRequest,
|
|||
if !sc.serviceable() {
|
||||
return nil, fmt.Errorf("ShardCluster for %s replicaID %d is no available", sc.vchannelName, sc.replicaID)
|
||||
}
|
||||
|
||||
if sc.vchannelName != req.GetDmlChannel() {
|
||||
return nil, fmt.Errorf("ShardCluster for %s does not match to request channel :%s", sc.vchannelName, req.GetDmlChannel())
|
||||
if !funcutil.SliceContain(req.GetDmlChannels(), sc.vchannelName) {
|
||||
return nil, fmt.Errorf("ShardCluster for %s does not match request channels :%v", sc.vchannelName, req.GetDmlChannels())
|
||||
}
|
||||
|
||||
// get node allocation and maintains the inUse reference count
|
||||
|
@ -766,10 +764,13 @@ func (sc *ShardCluster) Search(ctx context.Context, req *querypb.SearchRequest,
|
|||
|
||||
// dispatch request to followers
|
||||
for nodeID, segments := range segAllocs {
|
||||
nodeReq := proto.Clone(req).(*querypb.SearchRequest)
|
||||
nodeReq.FromShardLeader = true
|
||||
nodeReq.Scope = querypb.DataScope_Historical
|
||||
nodeReq.SegmentIDs = segments
|
||||
nodeReq := &querypb.SearchRequest{
|
||||
Req: req.Req,
|
||||
DmlChannels: req.DmlChannels,
|
||||
FromShardLeader: true,
|
||||
Scope: querypb.DataScope_Historical,
|
||||
SegmentIDs: segments,
|
||||
}
|
||||
node, ok := sc.getNode(nodeID)
|
||||
if !ok { // meta dismatch, report error
|
||||
return nil, fmt.Errorf("ShardCluster for %s replicaID %d is no available", sc.vchannelName, sc.replicaID)
|
||||
|
@ -808,8 +809,8 @@ func (sc *ShardCluster) Query(ctx context.Context, req *querypb.QueryRequest, wi
|
|||
}
|
||||
|
||||
// handles only the dml channel part, segment ids is dispatch by cluster itself
|
||||
if sc.vchannelName != req.GetDmlChannel() {
|
||||
return nil, fmt.Errorf("ShardCluster for %s does not match to request channel :%s", sc.vchannelName, req.GetDmlChannel())
|
||||
if !funcutil.SliceContain(req.GetDmlChannels(), sc.vchannelName) {
|
||||
return nil, fmt.Errorf("ShardCluster for %s does not match to request channels :%v", sc.vchannelName, req.GetDmlChannels())
|
||||
}
|
||||
|
||||
// get node allocation and maintains the inUse reference count
|
||||
|
@ -844,10 +845,13 @@ func (sc *ShardCluster) Query(ctx context.Context, req *querypb.QueryRequest, wi
|
|||
|
||||
// dispatch request to followers
|
||||
for nodeID, segments := range segAllocs {
|
||||
nodeReq := proto.Clone(req).(*querypb.QueryRequest)
|
||||
nodeReq.FromShardLeader = true
|
||||
nodeReq.SegmentIDs = segments
|
||||
nodeReq.Scope = querypb.DataScope_Historical
|
||||
nodeReq := &querypb.QueryRequest{
|
||||
Req: req.Req,
|
||||
FromShardLeader: true,
|
||||
SegmentIDs: segments,
|
||||
Scope: querypb.DataScope_Historical,
|
||||
DmlChannels: req.DmlChannels,
|
||||
}
|
||||
node, ok := sc.getNode(nodeID)
|
||||
if !ok { // meta dismatch, report error
|
||||
return nil, fmt.Errorf("SharcCluster for %s replicaID %d is no available", sc.vchannelName, sc.replicaID)
|
||||
|
|
|
@ -1018,7 +1018,7 @@ func TestShardCluster_Search(t *testing.T) {
|
|||
require.EqualValues(t, unavailable, sc.state.Load())
|
||||
|
||||
_, err := sc.Search(ctx, &querypb.SearchRequest{
|
||||
DmlChannel: vchannelName,
|
||||
DmlChannels: []string{vchannelName},
|
||||
}, streamingDoNothing)
|
||||
assert.Error(t, err)
|
||||
})
|
||||
|
@ -1030,7 +1030,7 @@ func TestShardCluster_Search(t *testing.T) {
|
|||
defer sc.Close()
|
||||
|
||||
_, err := sc.Search(ctx, &querypb.SearchRequest{
|
||||
DmlChannel: vchannelName + "_suffix",
|
||||
DmlChannels: []string{vchannelName + "_suffix"},
|
||||
}, streamingDoNothing)
|
||||
assert.Error(t, err)
|
||||
})
|
||||
|
@ -1079,7 +1079,7 @@ func TestShardCluster_Search(t *testing.T) {
|
|||
require.EqualValues(t, available, sc.state.Load())
|
||||
|
||||
result, err := sc.Search(ctx, &querypb.SearchRequest{
|
||||
DmlChannel: vchannelName,
|
||||
DmlChannels: []string{vchannelName},
|
||||
}, streamingDoNothing)
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, len(nodeEvents), len(result))
|
||||
|
@ -1129,7 +1129,7 @@ func TestShardCluster_Search(t *testing.T) {
|
|||
require.EqualValues(t, available, sc.state.Load())
|
||||
|
||||
_, err := sc.Search(ctx, &querypb.SearchRequest{
|
||||
DmlChannel: vchannelName,
|
||||
DmlChannels: []string{vchannelName},
|
||||
}, func(ctx context.Context) error { return errors.New("mocked") })
|
||||
assert.Error(t, err)
|
||||
})
|
||||
|
@ -1186,7 +1186,7 @@ func TestShardCluster_Search(t *testing.T) {
|
|||
require.EqualValues(t, available, sc.state.Load())
|
||||
|
||||
_, err := sc.Search(ctx, &querypb.SearchRequest{
|
||||
DmlChannel: vchannelName,
|
||||
DmlChannels: []string{vchannelName},
|
||||
}, streamingDoNothing)
|
||||
assert.Error(t, err)
|
||||
})
|
||||
|
@ -1238,7 +1238,7 @@ func TestShardCluster_Search(t *testing.T) {
|
|||
require.EqualValues(t, available, sc.state.Load())
|
||||
|
||||
_, err := sc.Search(ctx, &querypb.SearchRequest{
|
||||
DmlChannel: vchannelName,
|
||||
DmlChannels: []string{vchannelName},
|
||||
}, streamingDoNothing)
|
||||
assert.Error(t, err)
|
||||
})
|
||||
|
@ -1296,7 +1296,7 @@ func TestShardCluster_Query(t *testing.T) {
|
|||
require.EqualValues(t, unavailable, sc.state.Load())
|
||||
|
||||
_, err := sc.Query(ctx, &querypb.QueryRequest{
|
||||
DmlChannel: vchannelName,
|
||||
DmlChannels: []string{vchannelName},
|
||||
}, streamingDoNothing)
|
||||
assert.Error(t, err)
|
||||
})
|
||||
|
@ -1309,7 +1309,7 @@ func TestShardCluster_Query(t *testing.T) {
|
|||
sc.SyncSegments(nil, segmentStateLoaded)
|
||||
|
||||
_, err := sc.Query(ctx, &querypb.QueryRequest{
|
||||
DmlChannel: vchannelName + "_suffix",
|
||||
DmlChannels: []string{vchannelName + "_suffix"},
|
||||
}, streamingDoNothing)
|
||||
assert.Error(t, err)
|
||||
})
|
||||
|
@ -1357,7 +1357,7 @@ func TestShardCluster_Query(t *testing.T) {
|
|||
require.EqualValues(t, available, sc.state.Load())
|
||||
|
||||
result, err := sc.Query(ctx, &querypb.QueryRequest{
|
||||
DmlChannel: vchannelName,
|
||||
DmlChannels: []string{vchannelName},
|
||||
}, streamingDoNothing)
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, len(nodeEvents), len(result))
|
||||
|
@ -1406,7 +1406,7 @@ func TestShardCluster_Query(t *testing.T) {
|
|||
require.EqualValues(t, available, sc.state.Load())
|
||||
|
||||
_, err := sc.Query(ctx, &querypb.QueryRequest{
|
||||
DmlChannel: vchannelName,
|
||||
DmlChannels: []string{vchannelName},
|
||||
}, func(ctx context.Context) error { return errors.New("mocked") })
|
||||
assert.Error(t, err)
|
||||
})
|
||||
|
@ -1463,7 +1463,7 @@ func TestShardCluster_Query(t *testing.T) {
|
|||
require.EqualValues(t, available, sc.state.Load())
|
||||
|
||||
_, err := sc.Query(ctx, &querypb.QueryRequest{
|
||||
DmlChannel: vchannelName,
|
||||
DmlChannels: []string{vchannelName},
|
||||
}, streamingDoNothing)
|
||||
assert.Error(t, err)
|
||||
})
|
||||
|
@ -1515,7 +1515,7 @@ func TestShardCluster_Query(t *testing.T) {
|
|||
require.EqualValues(t, available, sc.state.Load())
|
||||
|
||||
_, err := sc.Query(ctx, &querypb.QueryRequest{
|
||||
DmlChannel: vchannelName,
|
||||
DmlChannels: []string{vchannelName},
|
||||
}, streamingDoNothing)
|
||||
assert.Error(t, err)
|
||||
})
|
||||
|
|
|
@ -89,6 +89,10 @@ func (s *searchTask) searchOnStreaming() error {
|
|||
return errors.New("search context timeout")
|
||||
}
|
||||
|
||||
if len(s.req.GetDmlChannels()) <= 0 {
|
||||
return errors.New("invalid nil dml channels")
|
||||
}
|
||||
|
||||
// check if collection has been released, check streaming since it's released first
|
||||
_, err := s.QS.metaReplica.getCollectionByID(s.CollectionID)
|
||||
if err != nil {
|
||||
|
@ -110,7 +114,7 @@ func (s *searchTask) searchOnStreaming() error {
|
|||
defer searchReq.delete()
|
||||
|
||||
// TODO add context
|
||||
partResults, _, _, sErr := searchStreaming(s.QS.metaReplica, searchReq, s.CollectionID, s.iReq.GetPartitionIDs(), s.req.GetDmlChannel())
|
||||
partResults, _, _, sErr := searchStreaming(s.QS.metaReplica, searchReq, s.CollectionID, s.iReq.GetPartitionIDs(), s.req.GetDmlChannels()[0])
|
||||
if sErr != nil {
|
||||
log.Debug("failed to search streaming data", zap.Int64("msgID", s.ID()),
|
||||
zap.Int64("collectionID", s.CollectionID), zap.Error(sErr))
|
||||
|
@ -181,7 +185,10 @@ func (s *searchTask) estimateCPUUsage() {
|
|||
if s.DataScope == querypb.DataScope_Streaming {
|
||||
// assume growing segments num is 5
|
||||
partitionIDs := s.iReq.GetPartitionIDs()
|
||||
channel := s.req.GetDmlChannel()
|
||||
channel := ""
|
||||
if len(s.req.GetDmlChannels()) > 0 {
|
||||
channel = s.req.GetDmlChannels()[0]
|
||||
}
|
||||
segIDs, err := s.QS.metaReplica.getSegmentIDsByVChannel(partitionIDs, channel, segmentTypeGrowing)
|
||||
if err != nil {
|
||||
log.Error("searchTask estimateCPUUsage", zap.Error(err))
|
||||
|
|
Loading…
Reference in New Issue