From ece592a42fae70e387991c933c61130f3641f4b6 Mon Sep 17 00:00:00 2001 From: yah01 Date: Tue, 7 Nov 2023 01:44:18 +0800 Subject: [PATCH] Deliver L0 segments delete records (#27722) Signed-off-by: yah01 --- internal/proto/query_coord.proto | 1 + internal/proto/querypb/query_coord.pb.go | 614 +++++++++--------- internal/querycoordv2/task/executor.go | 8 +- .../querynodev2/delegator/delegator_data.go | 80 ++- .../delegator/delegator_data_test.go | 21 + .../querynodev2/delegator/delegator_test.go | 1 + internal/querynodev2/handlers.go | 40 ++ internal/querynodev2/segments/manager.go | 27 +- internal/querynodev2/segments/manager_test.go | 8 +- internal/querynodev2/segments/mock_data.go | 2 +- internal/querynodev2/segments/mock_loader.go | 12 +- internal/querynodev2/segments/mock_segment.go | 161 ++++- .../segments/mock_segment_manager.go | 77 ++- internal/querynodev2/segments/reduce_test.go | 6 +- .../querynodev2/segments/retrieve_test.go | 11 +- internal/querynodev2/segments/search_test.go | 11 +- internal/querynodev2/segments/segment.go | 11 +- .../querynodev2/segments/segment_interface.go | 8 +- internal/querynodev2/segments/segment_l0.go | 164 +++++ .../querynodev2/segments/segment_loader.go | 67 +- internal/querynodev2/segments/segment_test.go | 27 +- internal/querynodev2/segments/utils.go | 16 + internal/querynodev2/server_test.go | 13 +- internal/querynodev2/services.go | 5 + internal/querynodev2/services_test.go | 17 + internal/storage/data_codec.go | 10 + internal/storage/data_codec_test.go | 19 + 27 files changed, 1006 insertions(+), 431 deletions(-) create mode 100644 internal/querynodev2/segments/segment_l0.go diff --git a/internal/proto/query_coord.proto b/internal/proto/query_coord.proto index abd08047b3a40..a962bcdc704db 100644 --- a/internal/proto/query_coord.proto +++ b/internal/proto/query_coord.proto @@ -258,6 +258,7 @@ message SegmentLoadInfo { msg.MsgPosition start_position = 14; msg.MsgPosition delta_position = 15; int64 readableVersion = 16; + data.SegmentLevel level = 17; } message FieldIndexInfo { diff --git a/internal/proto/querypb/query_coord.pb.go b/internal/proto/querypb/query_coord.pb.go index a11112412323e..65a2806a7a479 100644 --- a/internal/proto/querypb/query_coord.pb.go +++ b/internal/proto/querypb/query_coord.pb.go @@ -1615,6 +1615,7 @@ type SegmentLoadInfo struct { StartPosition *msgpb.MsgPosition `protobuf:"bytes,14,opt,name=start_position,json=startPosition,proto3" json:"start_position,omitempty"` DeltaPosition *msgpb.MsgPosition `protobuf:"bytes,15,opt,name=delta_position,json=deltaPosition,proto3" json:"delta_position,omitempty"` ReadableVersion int64 `protobuf:"varint,16,opt,name=readableVersion,proto3" json:"readableVersion,omitempty"` + Level datapb.SegmentLevel `protobuf:"varint,17,opt,name=level,proto3,enum=milvus.proto.data.SegmentLevel" json:"level,omitempty"` XXX_NoUnkeyedLiteral struct{} `json:"-"` XXX_unrecognized []byte `json:"-"` XXX_sizecache int32 `json:"-"` @@ -1757,6 +1758,13 @@ func (m *SegmentLoadInfo) GetReadableVersion() int64 { return 0 } +func (m *SegmentLoadInfo) GetLevel() datapb.SegmentLevel { + if m != nil { + return m.Level + } + return datapb.SegmentLevel_Legacy +} + type FieldIndexInfo struct { FieldID int64 `protobuf:"varint,1,opt,name=fieldID,proto3" json:"fieldID,omitempty"` // deprecated @@ -4594,309 +4602,311 @@ func init() { func init() { proto.RegisterFile("query_coord.proto", fileDescriptor_aab7cc9a69ed26e8) } var fileDescriptor_aab7cc9a69ed26e8 = []byte{ - // 4829 bytes of a gzipped FileDescriptorProto + // 4849 bytes of a gzipped FileDescriptorProto 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xec, 0x7c, 0xcb, 0x6f, 0x1c, 0x47, - 0x7a, 0xb8, 0x7a, 0x5e, 0x9c, 0xf9, 0xe6, 0xd5, 0x2c, 0x92, 0xd2, 0xec, 0xac, 0x24, 0xcb, 0x2d, - 0x3f, 0xb8, 0xb2, 0x4d, 0x6a, 0xa9, 0xb5, 0x57, 0xbb, 0xb6, 0xe1, 0x9f, 0x44, 0x5a, 0x32, 0xd7, - 0x36, 0xcd, 0x5f, 0x53, 0xf2, 0x06, 0x5e, 0xef, 0x8e, 0x9b, 0xd3, 0xc5, 0x61, 0x43, 0xfd, 0x18, - 0x75, 0xf7, 0x90, 0xa6, 0x03, 0x04, 0x39, 0xe4, 0x92, 0x4d, 0x36, 0x08, 0x92, 0x43, 0x72, 0x08, - 0x72, 0x48, 0x10, 0x60, 0x13, 0x24, 0x97, 0x20, 0x01, 0x72, 0xc8, 0x21, 0xb7, 0xe4, 0x92, 0xd7, - 0xff, 0x90, 0xdc, 0x72, 0xcc, 0x22, 0x30, 0x90, 0x43, 0x50, 0x8f, 0x7e, 0x54, 0x77, 0x0d, 0xa7, - 0xc9, 0x91, 0xfc, 0x08, 0x72, 0x9b, 0xfe, 0xea, 0xf1, 0x7d, 0xf5, 0xbd, 0xea, 0xfb, 0xbe, 0xaa, - 0x1a, 0x58, 0x7c, 0x3c, 0xc1, 0xfe, 0xc9, 0x60, 0xe8, 0x79, 0xbe, 0xb9, 0x36, 0xf6, 0xbd, 0xd0, - 0x43, 0xc8, 0xb1, 0xec, 0xa3, 0x49, 0xc0, 0xbe, 0xd6, 0x68, 0x7b, 0xbf, 0x35, 0xf4, 0x1c, 0xc7, - 0x73, 0x19, 0xac, 0xdf, 0x4a, 0xf7, 0xe8, 0x77, 0x2c, 0x37, 0xc4, 0xbe, 0x6b, 0xd8, 0x51, 0x6b, - 0x30, 0x3c, 0xc4, 0x8e, 0xc1, 0xbf, 0x1a, 0x4e, 0x30, 0xe2, 0x3f, 0x55, 0xd3, 0x08, 0x8d, 0x34, - 0xaa, 0xfe, 0xa2, 0xe5, 0x9a, 0xf8, 0xd3, 0x34, 0x48, 0xfb, 0x35, 0x05, 0x2e, 0xee, 0x1d, 0x7a, - 0xc7, 0x9b, 0x9e, 0x6d, 0xe3, 0x61, 0x68, 0x79, 0x6e, 0xa0, 0xe3, 0xc7, 0x13, 0x1c, 0x84, 0xe8, - 0x26, 0x54, 0xf6, 0x8d, 0x00, 0xf7, 0x94, 0x6b, 0xca, 0x6a, 0x73, 0xe3, 0xf2, 0x9a, 0x40, 0x27, - 0x27, 0xf0, 0xfd, 0x60, 0x74, 0xd7, 0x08, 0xb0, 0x4e, 0x7b, 0x22, 0x04, 0x15, 0x73, 0x7f, 0x7b, - 0xab, 0x57, 0xba, 0xa6, 0xac, 0x96, 0x75, 0xfa, 0x1b, 0x3d, 0x07, 0xed, 0x61, 0x3c, 0xf7, 0xf6, - 0x56, 0xd0, 0x2b, 0x5f, 0x2b, 0xaf, 0x96, 0x75, 0x11, 0xa8, 0xfd, 0xb4, 0x04, 0x97, 0x72, 0x64, - 0x04, 0x63, 0xcf, 0x0d, 0x30, 0xba, 0x05, 0xb5, 0x20, 0x34, 0xc2, 0x49, 0xc0, 0x29, 0xf9, 0xa6, - 0x94, 0x92, 0x3d, 0xda, 0x45, 0xe7, 0x5d, 0xf3, 0x68, 0x4b, 0x12, 0xb4, 0xe8, 0xdb, 0xb0, 0x6c, - 0xb9, 0xef, 0x63, 0xc7, 0xf3, 0x4f, 0x06, 0x63, 0xec, 0x0f, 0xb1, 0x1b, 0x1a, 0x23, 0x1c, 0xd1, - 0xb8, 0x14, 0xb5, 0xed, 0x26, 0x4d, 0xe8, 0x35, 0xb8, 0xc4, 0x64, 0x18, 0x60, 0xff, 0xc8, 0x1a, - 0xe2, 0x81, 0x71, 0x64, 0x58, 0xb6, 0xb1, 0x6f, 0xe3, 0x5e, 0xe5, 0x5a, 0x79, 0xb5, 0xae, 0xaf, - 0xd0, 0xe6, 0x3d, 0xd6, 0x7a, 0x27, 0x6a, 0x44, 0xdf, 0x02, 0xd5, 0xc7, 0x07, 0x3e, 0x0e, 0x0e, - 0x07, 0x63, 0xdf, 0x1b, 0xf9, 0x38, 0x08, 0x7a, 0x55, 0x8a, 0xa6, 0xcb, 0xe1, 0xbb, 0x1c, 0xac, - 0xfd, 0x89, 0x02, 0x2b, 0x84, 0x19, 0xbb, 0x86, 0x1f, 0x5a, 0x4f, 0x41, 0x24, 0x1a, 0xb4, 0xd2, - 0x6c, 0xe8, 0x95, 0x69, 0x9b, 0x00, 0x23, 0x7d, 0xc6, 0x11, 0x7a, 0xc2, 0xbe, 0x0a, 0x25, 0x55, - 0x80, 0x69, 0xff, 0xcc, 0x75, 0x27, 0x4d, 0xe7, 0x3c, 0x32, 0xcb, 0xe2, 0x2c, 0xe5, 0x71, 0x9e, - 0x47, 0x62, 0x32, 0xce, 0x57, 0xe4, 0x9c, 0xff, 0xc7, 0x32, 0xac, 0xbc, 0xe7, 0x19, 0x66, 0xa2, - 0x86, 0x5f, 0x3c, 0xe7, 0xdf, 0x84, 0x1a, 0xb3, 0xe8, 0x5e, 0x85, 0xe2, 0x7a, 0x5e, 0xc4, 0xc5, - 0xad, 0x3d, 0xa1, 0x70, 0x8f, 0x02, 0x74, 0x3e, 0x08, 0x3d, 0x0f, 0x1d, 0x1f, 0x8f, 0x6d, 0x6b, - 0x68, 0x0c, 0xdc, 0x89, 0xb3, 0x8f, 0xfd, 0x5e, 0xf5, 0x9a, 0xb2, 0x5a, 0xd5, 0xdb, 0x1c, 0xba, - 0x43, 0x81, 0xe8, 0x13, 0x68, 0x1f, 0x58, 0xd8, 0x36, 0x07, 0xd4, 0x25, 0x6c, 0x6f, 0xf5, 0x6a, - 0xd7, 0xca, 0xab, 0xcd, 0x8d, 0xd7, 0xd7, 0xf2, 0xde, 0x68, 0x4d, 0xca, 0x91, 0xb5, 0x7b, 0x64, - 0xf8, 0x36, 0x1b, 0xfd, 0xb6, 0x1b, 0xfa, 0x27, 0x7a, 0xeb, 0x20, 0x05, 0x42, 0x3d, 0x58, 0xe0, - 0xec, 0xed, 0x2d, 0x5c, 0x53, 0x56, 0xeb, 0x7a, 0xf4, 0x89, 0x5e, 0x84, 0xae, 0x8f, 0x03, 0x6f, - 0xe2, 0x0f, 0xf1, 0x60, 0xe4, 0x7b, 0x93, 0x71, 0xd0, 0xab, 0x5f, 0x2b, 0xaf, 0x36, 0xf4, 0x4e, - 0x04, 0xbe, 0x4f, 0xa1, 0xfd, 0xb7, 0x60, 0x31, 0x87, 0x05, 0xa9, 0x50, 0x7e, 0x84, 0x4f, 0xa8, - 0x20, 0xca, 0x3a, 0xf9, 0x89, 0x96, 0xa1, 0x7a, 0x64, 0xd8, 0x13, 0xcc, 0x59, 0xcd, 0x3e, 0xbe, - 0x5f, 0xba, 0xad, 0x68, 0x7f, 0xa0, 0x40, 0x4f, 0xc7, 0x36, 0x36, 0x02, 0xfc, 0x65, 0x8a, 0xf4, - 0x22, 0xd4, 0x5c, 0xcf, 0xc4, 0xdb, 0x5b, 0x54, 0xa4, 0x65, 0x9d, 0x7f, 0x69, 0x9f, 0x2b, 0xb0, - 0x7c, 0x1f, 0x87, 0xc4, 0x0c, 0xac, 0x20, 0xb4, 0x86, 0xb1, 0x9d, 0xbf, 0x09, 0x65, 0x1f, 0x3f, - 0xe6, 0x94, 0xbd, 0x24, 0x52, 0x16, 0xbb, 0x7f, 0xd9, 0x48, 0x9d, 0x8c, 0x43, 0xcf, 0x42, 0xcb, - 0x74, 0xec, 0xc1, 0xf0, 0xd0, 0x70, 0x5d, 0x6c, 0x33, 0x43, 0x6a, 0xe8, 0x4d, 0xd3, 0xb1, 0x37, - 0x39, 0x08, 0x5d, 0x05, 0x08, 0xf0, 0xc8, 0xc1, 0x6e, 0x98, 0xf8, 0xe4, 0x14, 0x04, 0xdd, 0x80, - 0xc5, 0x03, 0xdf, 0x73, 0x06, 0xc1, 0xa1, 0xe1, 0x9b, 0x03, 0x1b, 0x1b, 0x26, 0xf6, 0x29, 0xf5, - 0x75, 0xbd, 0x4b, 0x1a, 0xf6, 0x08, 0xfc, 0x3d, 0x0a, 0x46, 0xb7, 0xa0, 0x1a, 0x0c, 0xbd, 0x31, - 0xa6, 0x9a, 0xd6, 0xd9, 0xb8, 0x22, 0xd3, 0xa1, 0x2d, 0x23, 0x34, 0xf6, 0x48, 0x27, 0x9d, 0xf5, - 0xd5, 0xfe, 0xa6, 0xc2, 0x4c, 0xed, 0x2b, 0xee, 0xe4, 0x52, 0xe6, 0x58, 0x7d, 0x32, 0xe6, 0x58, - 0x2b, 0x64, 0x8e, 0x0b, 0xa7, 0x9b, 0x63, 0x8e, 0x6b, 0x67, 0x31, 0xc7, 0xfa, 0x4c, 0x73, 0x6c, - 0xc8, 0xcc, 0x11, 0xbd, 0x0d, 0x5d, 0x16, 0x40, 0x58, 0xee, 0x81, 0x37, 0xb0, 0xad, 0x20, 0xec, - 0x01, 0x25, 0xf3, 0x4a, 0x56, 0x43, 0x4d, 0xfc, 0xe9, 0x1a, 0x43, 0xec, 0x1e, 0x78, 0x7a, 0xdb, - 0x8a, 0x7e, 0xbe, 0x67, 0x05, 0xe1, 0xfc, 0x56, 0xfd, 0x77, 0x89, 0x55, 0x7f, 0xd5, 0xb5, 0x27, - 0xb1, 0xfc, 0xaa, 0x60, 0xf9, 0x7f, 0xaa, 0xc0, 0x37, 0xee, 0xe3, 0x30, 0x26, 0x9f, 0x18, 0x32, - 0xfe, 0x8a, 0x6e, 0xf3, 0x7f, 0xa1, 0x40, 0x5f, 0x46, 0xeb, 0x3c, 0x5b, 0xfd, 0x47, 0x70, 0x31, - 0xc6, 0x31, 0x30, 0x71, 0x30, 0xf4, 0xad, 0x31, 0x15, 0x23, 0xf5, 0x55, 0xcd, 0x8d, 0xeb, 0x32, - 0xc5, 0xcf, 0x52, 0xb0, 0x12, 0x4f, 0xb1, 0x95, 0x9a, 0x41, 0xfb, 0x99, 0x02, 0x2b, 0xc4, 0x37, - 0x72, 0x67, 0x46, 0x34, 0xf0, 0xdc, 0x7c, 0x15, 0xdd, 0x64, 0x29, 0xe7, 0x26, 0x0b, 0xf0, 0x98, - 0x86, 0xd8, 0x59, 0x7a, 0xe6, 0xe1, 0xdd, 0xab, 0x50, 0x25, 0x06, 0x18, 0xb1, 0xea, 0x19, 0x19, - 0xab, 0xd2, 0xc8, 0x58, 0x6f, 0xcd, 0x65, 0x54, 0x24, 0x7e, 0x7b, 0x0e, 0x75, 0xcb, 0x2e, 0xbb, - 0x24, 0x59, 0xf6, 0x6f, 0x2a, 0x70, 0x29, 0x87, 0x70, 0x9e, 0x75, 0xbf, 0x01, 0x35, 0xba, 0x1b, - 0x45, 0x0b, 0x7f, 0x4e, 0xba, 0xf0, 0x14, 0x3a, 0xe2, 0x6d, 0x74, 0x3e, 0x46, 0xf3, 0x40, 0xcd, - 0xb6, 0x91, 0x7d, 0x92, 0xef, 0x91, 0x03, 0xd7, 0x70, 0x18, 0x03, 0x1a, 0x7a, 0x93, 0xc3, 0x76, - 0x0c, 0x07, 0xa3, 0x6f, 0x40, 0x9d, 0x98, 0xec, 0xc0, 0x32, 0x23, 0xf1, 0x2f, 0x50, 0x13, 0x36, - 0x03, 0x74, 0x05, 0x80, 0x36, 0x19, 0xa6, 0xe9, 0xb3, 0x2d, 0xb4, 0xa1, 0x37, 0x08, 0xe4, 0x0e, - 0x01, 0x68, 0xbf, 0xaf, 0xc0, 0xd5, 0xbd, 0x13, 0x77, 0xb8, 0x83, 0x8f, 0x37, 0x7d, 0x6c, 0x84, - 0x38, 0x71, 0xda, 0x4f, 0x95, 0xf1, 0xe8, 0x1a, 0x34, 0x53, 0xf6, 0xcb, 0x55, 0x32, 0x0d, 0xd2, - 0xfe, 0x52, 0x81, 0x16, 0xd9, 0x45, 0xde, 0xc7, 0xa1, 0x41, 0x54, 0x04, 0x7d, 0x0f, 0x1a, 0xb6, - 0x67, 0x98, 0x83, 0xf0, 0x64, 0xcc, 0xa8, 0xe9, 0x64, 0xa9, 0x49, 0xb6, 0x9e, 0x07, 0x27, 0x63, - 0xac, 0xd7, 0x6d, 0xfe, 0xab, 0x10, 0x45, 0x59, 0x2f, 0x53, 0x96, 0x78, 0xca, 0x67, 0xa0, 0xe9, - 0xe0, 0xd0, 0xb7, 0x86, 0x8c, 0x88, 0x0a, 0x15, 0x05, 0x30, 0x10, 0x41, 0xa4, 0xfd, 0xac, 0x06, - 0x17, 0x7f, 0x68, 0x84, 0xc3, 0xc3, 0x2d, 0x27, 0x8a, 0x62, 0xce, 0xcf, 0xc7, 0xc4, 0x2f, 0x97, - 0xd2, 0x7e, 0xf9, 0x89, 0xf9, 0xfd, 0xd8, 0x46, 0xab, 0x32, 0x1b, 0x25, 0x89, 0xf9, 0xda, 0x87, - 0x5c, 0xcd, 0x52, 0x36, 0x9a, 0x0a, 0x36, 0x6a, 0xe7, 0x09, 0x36, 0x36, 0xa1, 0x8d, 0x3f, 0x1d, - 0xda, 0x13, 0xa2, 0xaf, 0x14, 0x3b, 0x8b, 0x22, 0xae, 0x4a, 0xb0, 0xa7, 0x1d, 0x44, 0x8b, 0x0f, - 0xda, 0xe6, 0x34, 0x30, 0x5d, 0x70, 0x70, 0x68, 0xd0, 0x50, 0xa1, 0xb9, 0x71, 0x6d, 0x9a, 0x2e, - 0x44, 0x0a, 0xc4, 0xf4, 0x81, 0x7c, 0xa1, 0xcb, 0xd0, 0xe0, 0xa1, 0xcd, 0xf6, 0x56, 0xaf, 0x41, - 0xd9, 0x97, 0x00, 0x90, 0x01, 0x6d, 0xee, 0x3d, 0x39, 0x85, 0x2c, 0x80, 0x78, 0x43, 0x86, 0x40, - 0x2e, 0xec, 0x34, 0xe5, 0x01, 0x0f, 0x74, 0x82, 0x14, 0x88, 0x64, 0xfe, 0xde, 0xc1, 0x81, 0x6d, - 0xb9, 0x78, 0x87, 0x49, 0xb8, 0x49, 0x89, 0x10, 0x81, 0x24, 0x1c, 0x3a, 0xc2, 0x7e, 0x60, 0x79, - 0x6e, 0xaf, 0x45, 0xdb, 0xa3, 0x4f, 0x59, 0x94, 0xd3, 0x3e, 0x47, 0x94, 0x33, 0x80, 0xc5, 0x1c, - 0xa5, 0x92, 0x28, 0xe7, 0x3b, 0xe9, 0x28, 0x67, 0xb6, 0xa8, 0x52, 0x51, 0xd0, 0xcf, 0x15, 0x58, - 0x79, 0xe8, 0x06, 0x93, 0xfd, 0x98, 0x45, 0x5f, 0x8e, 0x39, 0x64, 0x9d, 0x68, 0x25, 0xe7, 0x44, - 0xb5, 0xff, 0xac, 0x42, 0x97, 0xaf, 0x82, 0x68, 0x0d, 0x75, 0x39, 0x97, 0xa1, 0x11, 0xef, 0xa3, - 0x9c, 0x21, 0x09, 0x20, 0xeb, 0xc3, 0x4a, 0x39, 0x1f, 0x56, 0x88, 0xb4, 0x28, 0x2a, 0xaa, 0xa4, - 0xa2, 0xa2, 0x2b, 0x00, 0x07, 0xf6, 0x24, 0x38, 0x1c, 0x84, 0x96, 0x83, 0x79, 0x54, 0xd6, 0xa0, - 0x90, 0x07, 0x96, 0x83, 0xd1, 0x1d, 0x68, 0xed, 0x5b, 0xae, 0xed, 0x8d, 0x06, 0x63, 0x23, 0x3c, - 0x0c, 0x78, 0x5a, 0x2c, 0x13, 0x0b, 0x8d, 0x61, 0xef, 0xd2, 0xbe, 0x7a, 0x93, 0x8d, 0xd9, 0x25, - 0x43, 0xd0, 0x55, 0x68, 0xba, 0x13, 0x67, 0xe0, 0x1d, 0x0c, 0x7c, 0xef, 0x38, 0xa0, 0xc9, 0x6f, - 0x59, 0x6f, 0xb8, 0x13, 0xe7, 0x83, 0x03, 0xdd, 0x3b, 0x26, 0xfb, 0x58, 0x83, 0xec, 0x68, 0x81, - 0xed, 0x8d, 0x58, 0xe2, 0x3b, 0x7b, 0xfe, 0x64, 0x00, 0x19, 0x6d, 0x62, 0x3b, 0x34, 0xe8, 0xe8, - 0x46, 0xb1, 0xd1, 0xf1, 0x00, 0xf4, 0x02, 0x74, 0x86, 0x9e, 0x33, 0x36, 0x28, 0x87, 0xee, 0xf9, - 0x9e, 0x43, 0x0d, 0xb0, 0xac, 0x67, 0xa0, 0x68, 0x13, 0x9a, 0x89, 0x11, 0x04, 0xbd, 0x26, 0xc5, - 0xa3, 0xc9, 0xac, 0x34, 0x15, 0xca, 0x13, 0x05, 0x85, 0xd8, 0x0a, 0x02, 0xa2, 0x19, 0x91, 0xb1, - 0x07, 0xd6, 0x67, 0x98, 0x1b, 0x5a, 0x93, 0xc3, 0xf6, 0xac, 0xcf, 0x30, 0x49, 0x8f, 0x2c, 0x37, - 0xc0, 0x7e, 0x18, 0x25, 0xab, 0xbd, 0x36, 0x55, 0x9f, 0x36, 0x83, 0x72, 0xc5, 0x46, 0x5b, 0xd0, - 0x09, 0x42, 0xc3, 0x0f, 0x07, 0x63, 0x2f, 0xa0, 0x0a, 0xd0, 0xeb, 0x50, 0xdd, 0xce, 0x98, 0xa4, - 0x13, 0x8c, 0x88, 0x62, 0xef, 0xf2, 0x4e, 0x7a, 0x9b, 0x0e, 0x8a, 0x3e, 0xc9, 0x2c, 0x94, 0x13, - 0xc9, 0x2c, 0xdd, 0x42, 0xb3, 0xd0, 0x41, 0xf1, 0x2c, 0xab, 0x24, 0x5d, 0x32, 0x4c, 0x63, 0xdf, - 0xc6, 0x1f, 0x72, 0x0f, 0xa2, 0xd2, 0x85, 0x65, 0xc1, 0xda, 0x1f, 0x97, 0xa1, 0x23, 0xb2, 0x87, - 0xb8, 0x1d, 0x96, 0x95, 0x45, 0x3a, 0x1f, 0x7d, 0x12, 0x66, 0x61, 0x97, 0x8c, 0x66, 0x29, 0x20, - 0x55, 0xf9, 0xba, 0xde, 0x64, 0x30, 0x3a, 0x01, 0x51, 0x5d, 0x26, 0x14, 0x6a, 0x67, 0x65, 0xca, - 0xa8, 0x06, 0x85, 0xd0, 0x50, 0xa5, 0x07, 0x0b, 0x51, 0xf6, 0xc8, 0x14, 0x3e, 0xfa, 0x24, 0x2d, - 0xfb, 0x13, 0x8b, 0x62, 0x65, 0x0a, 0x1f, 0x7d, 0xa2, 0x2d, 0x68, 0xb1, 0x29, 0xc7, 0x86, 0x6f, - 0x38, 0x91, 0xba, 0x3f, 0x2b, 0x75, 0x19, 0xef, 0xe2, 0x93, 0x0f, 0x89, 0xf7, 0xd9, 0x35, 0x2c, - 0x5f, 0x67, 0xea, 0xb1, 0x4b, 0x47, 0xa1, 0x55, 0x50, 0xd9, 0x2c, 0x07, 0x96, 0x8d, 0xb9, 0xe1, - 0x2c, 0xb0, 0x14, 0x92, 0xc2, 0xef, 0x59, 0x36, 0x66, 0xb6, 0x11, 0x2f, 0x81, 0x2a, 0x44, 0x9d, - 0x99, 0x06, 0x85, 0x50, 0x75, 0xb8, 0x0e, 0xcc, 0x8b, 0x0e, 0x22, 0xdf, 0xcc, 0x36, 0x10, 0x46, - 0x23, 0x67, 0x2b, 0x0d, 0xc9, 0x26, 0x0e, 0x33, 0x2e, 0x60, 0xcb, 0x71, 0x27, 0x0e, 0x35, 0xad, - 0x0d, 0x58, 0x19, 0x4e, 0x7c, 0x9f, 0x6d, 0x2f, 0xe9, 0x79, 0x9a, 0x34, 0xe9, 0x5e, 0xe2, 0x8d, - 0xdb, 0xa9, 0xe9, 0xb4, 0xdf, 0xa9, 0xc2, 0x12, 0xf1, 0x4a, 0xdc, 0x41, 0xcd, 0x11, 0x54, 0x5c, - 0x01, 0x30, 0x83, 0x70, 0x20, 0x78, 0xd2, 0x86, 0x19, 0x84, 0x7c, 0xcb, 0xf9, 0x5e, 0x14, 0x13, - 0x94, 0xa7, 0xa7, 0x38, 0x19, 0x2f, 0x99, 0x8f, 0x0b, 0xce, 0x55, 0x13, 0xbc, 0x0e, 0x6d, 0x9e, - 0xdf, 0x0b, 0xc9, 0x68, 0x8b, 0x01, 0x77, 0xe4, 0xbe, 0xbe, 0x26, 0xad, 0x4d, 0xa6, 0x62, 0x83, - 0x85, 0xf9, 0x62, 0x83, 0x7a, 0x36, 0x36, 0xb8, 0x07, 0x5d, 0xd1, 0x3c, 0x23, 0xff, 0x36, 0xc3, - 0x3e, 0x3b, 0x82, 0x7d, 0x06, 0xe9, 0xad, 0x1d, 0xc4, 0xad, 0xfd, 0x3a, 0xb4, 0x5d, 0x8c, 0xcd, - 0x41, 0xe8, 0x1b, 0x6e, 0x70, 0x80, 0x7d, 0xaa, 0x16, 0x75, 0xbd, 0x45, 0x80, 0x0f, 0x38, 0x0c, - 0xbd, 0x01, 0x40, 0xd7, 0xc8, 0x4a, 0x5a, 0xad, 0xe9, 0x25, 0x2d, 0xaa, 0x34, 0xb4, 0xa4, 0x45, - 0x99, 0x42, 0x7f, 0x3e, 0xa1, 0xe8, 0x41, 0xfb, 0xa7, 0x12, 0x5c, 0xe4, 0x25, 0x8e, 0xf9, 0xf5, - 0x72, 0xda, 0xee, 0x1e, 0x6d, 0x8f, 0xe5, 0x53, 0x8a, 0x06, 0x95, 0x02, 0x01, 0x70, 0x55, 0x12, - 0x00, 0x8b, 0x89, 0x73, 0x2d, 0x97, 0x38, 0xc7, 0x35, 0xc3, 0x85, 0xe2, 0x35, 0x43, 0xb4, 0x0c, - 0x55, 0x9a, 0xcd, 0x51, 0xdd, 0x69, 0xe8, 0xec, 0xa3, 0x90, 0x54, 0xb5, 0xdf, 0x2b, 0x41, 0x7b, - 0x0f, 0x1b, 0xfe, 0xf0, 0x30, 0xe2, 0xe3, 0x6b, 0xe9, 0x1a, 0xeb, 0x73, 0x53, 0x6a, 0xac, 0xc2, - 0x90, 0xaf, 0x4d, 0x71, 0x95, 0x20, 0x08, 0xbd, 0xd0, 0x88, 0xa9, 0x1c, 0xb8, 0x13, 0x87, 0x17, - 0x1e, 0xbb, 0xb4, 0x81, 0x93, 0xba, 0x33, 0x71, 0xb4, 0xff, 0x50, 0xa0, 0xf5, 0xff, 0xc9, 0x34, - 0x11, 0x63, 0x6e, 0xa7, 0x19, 0xf3, 0xc2, 0x14, 0xc6, 0xe8, 0x24, 0x31, 0xc3, 0x47, 0xf8, 0x6b, - 0x57, 0x77, 0xfe, 0x7b, 0x05, 0xfa, 0x24, 0x2d, 0xd7, 0x99, 0xdf, 0x99, 0xdf, 0xba, 0xae, 0x43, - 0xfb, 0x48, 0x08, 0x80, 0x4b, 0x54, 0x39, 0x5b, 0x47, 0xe9, 0x32, 0x82, 0x0e, 0x6a, 0x54, 0x06, - 0xe6, 0x8b, 0x8d, 0xb6, 0x81, 0x17, 0x65, 0x54, 0x67, 0x88, 0xa3, 0x1e, 0xa2, 0xeb, 0x8b, 0x40, - 0xed, 0xb7, 0x14, 0x58, 0x92, 0x74, 0x44, 0x97, 0x60, 0x81, 0x97, 0x2c, 0x78, 0x8c, 0xc1, 0xec, - 0xdd, 0x24, 0xe2, 0x49, 0x8a, 0x6e, 0x96, 0x99, 0x8f, 0xaa, 0x4d, 0x92, 0x85, 0xc7, 0xf9, 0x99, - 0x99, 0x93, 0x8f, 0x19, 0xa0, 0x3e, 0xd4, 0xb9, 0x37, 0x8d, 0x12, 0xdf, 0xf8, 0x5b, 0x7b, 0x04, - 0xe8, 0x3e, 0x4e, 0xf6, 0xae, 0x79, 0x38, 0x9a, 0xf8, 0x9b, 0x84, 0xd0, 0xb4, 0x13, 0x32, 0xb5, - 0x7f, 0x53, 0x60, 0x49, 0xc0, 0x36, 0x4f, 0x69, 0x29, 0xd9, 0x5f, 0x4b, 0xe7, 0xd9, 0x5f, 0x85, - 0xf2, 0x49, 0xf9, 0x4c, 0xe5, 0x93, 0xab, 0x00, 0x31, 0xff, 0x23, 0x8e, 0xa6, 0x20, 0xda, 0xdf, - 0x2a, 0x70, 0xf1, 0x1d, 0xc3, 0x35, 0xbd, 0x83, 0x83, 0xf9, 0x55, 0x75, 0x13, 0x84, 0x54, 0xb9, - 0x68, 0x01, 0x51, 0xcc, 0xaf, 0x5f, 0x82, 0x45, 0x9f, 0xed, 0x4c, 0xa6, 0xa8, 0xcb, 0x65, 0x5d, - 0x8d, 0x1a, 0x62, 0x1d, 0xfd, 0xf3, 0x12, 0x20, 0xb2, 0xea, 0xbb, 0x86, 0x6d, 0xb8, 0x43, 0x7c, - 0x7e, 0xd2, 0x9f, 0x87, 0x8e, 0x10, 0xc2, 0xc4, 0x07, 0xfa, 0xe9, 0x18, 0x26, 0x40, 0xef, 0x42, - 0x67, 0x9f, 0xa1, 0x1a, 0xf8, 0xd8, 0x08, 0x3c, 0x97, 0x8b, 0x43, 0x5a, 0x2b, 0x7c, 0xe0, 0x5b, - 0xa3, 0x11, 0xf6, 0x37, 0x3d, 0xd7, 0xe4, 0x91, 0xfe, 0x7e, 0x44, 0x26, 0x19, 0x4a, 0x8c, 0x21, - 0x89, 0xe7, 0x62, 0xe1, 0xc4, 0x01, 0x1d, 0x65, 0x45, 0x80, 0x0d, 0x3b, 0x61, 0x44, 0xb2, 0x1b, - 0xaa, 0xac, 0x61, 0x6f, 0x7a, 0xa9, 0x58, 0x12, 0x5f, 0x69, 0x7f, 0xa5, 0x00, 0x8a, 0xd3, 0x79, - 0x5a, 0xff, 0xa0, 0x16, 0x9d, 0x1d, 0xaa, 0x48, 0x36, 0xe5, 0xcb, 0xd0, 0x30, 0xa3, 0x91, 0xdc, - 0x05, 0x25, 0x00, 0xba, 0x47, 0x52, 0xa2, 0x07, 0x44, 0xf3, 0xb0, 0x19, 0xa5, 0xcb, 0x0c, 0xf8, - 0x1e, 0x85, 0x89, 0xe1, 0x59, 0x25, 0x1b, 0x9e, 0xa5, 0x2b, 0xa1, 0x55, 0xa1, 0x12, 0xaa, 0xfd, - 0xbc, 0x04, 0x2a, 0xdd, 0x42, 0x36, 0x93, 0x92, 0x56, 0x21, 0xa2, 0xaf, 0x43, 0x9b, 0x5f, 0x88, - 0x11, 0x08, 0x6f, 0x3d, 0x4e, 0x4d, 0x86, 0x6e, 0xc2, 0x32, 0xeb, 0xe4, 0xe3, 0x60, 0x62, 0x27, - 0x99, 0x22, 0x4b, 0x80, 0xd0, 0x63, 0xb6, 0x77, 0x91, 0xa6, 0x68, 0xc4, 0x43, 0xb8, 0x38, 0xb2, - 0xbd, 0x7d, 0xc3, 0x1e, 0x88, 0xe2, 0x61, 0x32, 0x2c, 0xa0, 0xf1, 0xcb, 0x6c, 0xf8, 0x5e, 0x5a, - 0x86, 0x01, 0xba, 0x0b, 0xed, 0x00, 0xe3, 0x47, 0x49, 0xfa, 0x58, 0x2d, 0x92, 0x3e, 0xb6, 0xc8, - 0x98, 0xe8, 0x4b, 0xfb, 0x43, 0x05, 0xba, 0x99, 0x73, 0x8c, 0x6c, 0xb1, 0x43, 0xc9, 0x17, 0x3b, - 0x6e, 0x43, 0x95, 0x78, 0x2a, 0xb6, 0xb7, 0x74, 0xe4, 0x89, 0xb8, 0x38, 0xab, 0xce, 0x06, 0xa0, - 0x75, 0x58, 0x92, 0xdc, 0x97, 0xe0, 0xe2, 0x47, 0xf9, 0xeb, 0x12, 0xda, 0x2f, 0x2a, 0xd0, 0x4c, - 0xb1, 0x62, 0x46, 0x9d, 0xe6, 0x89, 0xd4, 0xa3, 0xa7, 0x9d, 0x8f, 0x13, 0x95, 0x73, 0xb0, 0xc3, - 0x72, 0x45, 0x9e, 0xb8, 0x3a, 0xd8, 0xa1, 0x99, 0x62, 0x3a, 0x09, 0xac, 0x89, 0x49, 0xa0, 0x98, - 0x26, 0x2f, 0x9c, 0x92, 0x26, 0xd7, 0xc5, 0x34, 0x59, 0x30, 0xa1, 0x46, 0xd6, 0x84, 0x8a, 0x96, - 0x4e, 0x6e, 0xc2, 0xd2, 0x90, 0xd5, 0xfb, 0xef, 0x9e, 0x6c, 0xc6, 0x4d, 0x3c, 0x28, 0x95, 0x35, - 0xa1, 0x7b, 0x49, 0x51, 0x94, 0x49, 0x99, 0x25, 0x1d, 0xf2, 0x2c, 0x9c, 0xcb, 0x86, 0x09, 0x39, - 0xf2, 0xcc, 0xf4, 0x2b, 0x5b, 0xb4, 0x69, 0x9f, 0xab, 0x68, 0xf3, 0x0c, 0x34, 0xa3, 0x48, 0x85, - 0x58, 0x7a, 0x87, 0x39, 0xbd, 0xc8, 0x0d, 0x98, 0x81, 0xe0, 0x07, 0xba, 0xe2, 0x89, 0x48, 0xb6, - 0x86, 0xa1, 0xe6, 0x6b, 0x18, 0x97, 0x60, 0xc1, 0x0a, 0x06, 0x07, 0xc6, 0x23, 0xdc, 0x5b, 0xa4, - 0xad, 0x35, 0x2b, 0xb8, 0x67, 0x3c, 0xc2, 0xda, 0xbf, 0x94, 0xa1, 0x93, 0x6c, 0xb0, 0x85, 0x3d, - 0x48, 0x91, 0x3b, 0x43, 0x3b, 0xa0, 0x26, 0x71, 0x0f, 0xe5, 0xf0, 0xa9, 0x39, 0x78, 0xf6, 0x98, - 0xb1, 0x3b, 0xce, 0xd8, 0xab, 0xb0, 0xdd, 0x57, 0xce, 0xb4, 0xdd, 0xcf, 0x79, 0x9b, 0xe0, 0x16, - 0xac, 0xc4, 0x7b, 0xaf, 0xb0, 0x6c, 0x96, 0x60, 0x2d, 0x47, 0x8d, 0xbb, 0xe9, 0xe5, 0x4f, 0x71, - 0x01, 0x0b, 0xd3, 0x5c, 0x40, 0x56, 0x05, 0xea, 0x39, 0x15, 0xc8, 0x5f, 0x6a, 0x68, 0x48, 0x2e, - 0x35, 0x68, 0x0f, 0x61, 0x89, 0x16, 0xa8, 0x83, 0xa1, 0x6f, 0xed, 0xe3, 0x38, 0x05, 0x28, 0x22, - 0xd6, 0x3e, 0xd4, 0x33, 0x59, 0x44, 0xfc, 0xad, 0xfd, 0x54, 0x81, 0x8b, 0xf9, 0x79, 0xa9, 0xc6, - 0x24, 0x8e, 0x44, 0x11, 0x1c, 0xc9, 0x2f, 0xc1, 0x52, 0x2a, 0xa2, 0x14, 0x66, 0x9e, 0x12, 0x81, - 0x4b, 0x08, 0xd7, 0x51, 0x32, 0x47, 0x04, 0xd3, 0x7e, 0xa1, 0xc4, 0x75, 0x7e, 0x02, 0x1b, 0xd1, - 0x43, 0x14, 0xb2, 0xaf, 0x79, 0xae, 0x6d, 0xb9, 0x71, 0xc1, 0x85, 0xaf, 0x91, 0x01, 0x79, 0xc1, - 0xe5, 0x1d, 0xe8, 0xf2, 0x4e, 0xf1, 0xf6, 0x54, 0x30, 0x20, 0xeb, 0xb0, 0x71, 0xf1, 0xc6, 0xf4, - 0x3c, 0x74, 0xf8, 0xe9, 0x46, 0x84, 0xaf, 0x2c, 0x3b, 0xf3, 0xf8, 0x01, 0xa8, 0x51, 0xb7, 0xb3, - 0x6e, 0x88, 0x5d, 0x3e, 0x30, 0x0e, 0xec, 0x7e, 0x5d, 0x81, 0x9e, 0xb8, 0x3d, 0xa6, 0x96, 0x7f, - 0xf6, 0xf0, 0xee, 0x75, 0xf1, 0x4c, 0xfb, 0xf9, 0x53, 0xe8, 0x49, 0xf0, 0x44, 0x27, 0xdb, 0xbf, - 0x5d, 0xa2, 0x17, 0x14, 0x48, 0xaa, 0xb7, 0x65, 0x05, 0xa1, 0x6f, 0xed, 0x4f, 0xe6, 0x3b, 0x65, - 0x35, 0xa0, 0x39, 0x3c, 0xc4, 0xc3, 0x47, 0x63, 0xcf, 0x4a, 0xa4, 0xf2, 0x96, 0x8c, 0xa6, 0xe9, - 0x68, 0xd7, 0x36, 0x93, 0x19, 0xd8, 0x31, 0x55, 0x7a, 0xce, 0xfe, 0x8f, 0x41, 0xcd, 0x76, 0x48, - 0x9f, 0x0e, 0x35, 0xd8, 0xe9, 0xd0, 0x2d, 0xf1, 0x74, 0x68, 0x46, 0xa4, 0x91, 0x3a, 0x1c, 0xfa, - 0xeb, 0x12, 0x7c, 0x53, 0x4a, 0xdb, 0x3c, 0x59, 0xd2, 0xb4, 0x3a, 0xd2, 0x5d, 0xa8, 0x67, 0x92, - 0xda, 0x17, 0x4e, 0x91, 0x1f, 0xaf, 0xbb, 0xb2, 0xd2, 0x60, 0x90, 0xc4, 0x56, 0x89, 0xc1, 0x57, - 0xa6, 0xcf, 0xc1, 0xed, 0x4e, 0x98, 0x23, 0x1a, 0x87, 0xee, 0x40, 0x8b, 0x15, 0x0c, 0x06, 0x47, - 0x16, 0x3e, 0x8e, 0xce, 0x5e, 0xaf, 0x4a, 0x5d, 0x33, 0xed, 0xf7, 0xa1, 0x85, 0x8f, 0xf5, 0xa6, - 0x1d, 0xff, 0x0e, 0xb4, 0xdf, 0xad, 0x00, 0x24, 0x6d, 0x24, 0x3b, 0x4b, 0x6c, 0x9e, 0x1b, 0x71, - 0x0a, 0x42, 0x62, 0x09, 0x31, 0x72, 0x8d, 0x3e, 0x91, 0x9e, 0x9c, 0x7d, 0x98, 0x56, 0x10, 0x72, - 0xbe, 0xac, 0x9f, 0x4e, 0x4b, 0xc4, 0x22, 0x22, 0x32, 0xae, 0x33, 0x41, 0x02, 0x41, 0xaf, 0x00, - 0x1a, 0xf9, 0xde, 0xb1, 0xe5, 0x8e, 0xd2, 0xf9, 0x06, 0x4b, 0x4b, 0x16, 0x79, 0x4b, 0x2a, 0xe1, - 0xf8, 0x09, 0xa8, 0x99, 0xee, 0x11, 0x4b, 0x6e, 0xcd, 0x20, 0xe3, 0xbe, 0x30, 0x17, 0x57, 0xdf, - 0xae, 0x88, 0x81, 0x1e, 0xb4, 0x3e, 0x30, 0xfc, 0x11, 0x8e, 0x24, 0xca, 0xe3, 0x30, 0x11, 0xd8, - 0x1f, 0x80, 0x9a, 0x5d, 0x95, 0xe4, 0x18, 0xf4, 0x55, 0x51, 0xd1, 0x4f, 0xf3, 0x47, 0x64, 0x9a, - 0x94, 0xaa, 0xf7, 0x0d, 0x58, 0x96, 0xd1, 0x2b, 0x41, 0x72, 0x6e, 0x6b, 0x7a, 0x2b, 0x0e, 0x89, - 0xa9, 0x1c, 0xa6, 0xed, 0x32, 0xa9, 0xc2, 0x73, 0x49, 0x28, 0x3c, 0x6b, 0xbf, 0x5a, 0x06, 0x94, - 0x57, 0x7f, 0xd4, 0x81, 0x52, 0x3c, 0x49, 0x69, 0x7b, 0x2b, 0xa3, 0x6e, 0xa5, 0x9c, 0xba, 0x5d, - 0x86, 0x46, 0xbc, 0xeb, 0x73, 0x17, 0x9f, 0x00, 0xd2, 0xca, 0x58, 0x11, 0x95, 0x31, 0x45, 0x58, - 0x55, 0xac, 0x88, 0xdf, 0x84, 0x65, 0xdb, 0x08, 0xc2, 0x01, 0x2b, 0xbc, 0x87, 0x96, 0x83, 0x83, - 0xd0, 0x70, 0xc6, 0x54, 0x94, 0x15, 0x1d, 0x91, 0xb6, 0x2d, 0xd2, 0xf4, 0x20, 0x6a, 0x41, 0x0f, - 0xa2, 0xe8, 0x9a, 0xf8, 0x5e, 0x7e, 0xc1, 0xe0, 0xd5, 0x62, 0xe6, 0x9e, 0x94, 0xbb, 0x99, 0x46, - 0x35, 0xe2, 0xb0, 0xb3, 0xff, 0x09, 0x74, 0xc4, 0x46, 0x89, 0xf8, 0x6e, 0x8b, 0xe2, 0x2b, 0x12, - 0xd8, 0xa6, 0x64, 0x78, 0x08, 0x28, 0xef, 0x3c, 0xd2, 0x3c, 0x53, 0x44, 0x9e, 0xcd, 0x92, 0x45, - 0x8a, 0xa7, 0x65, 0x51, 0xd8, 0xff, 0x50, 0x06, 0x94, 0x44, 0x70, 0xf1, 0x81, 0x77, 0x91, 0xb0, - 0x67, 0x1d, 0x96, 0xf2, 0xf1, 0x5d, 0x14, 0xd4, 0xa2, 0x5c, 0x74, 0x27, 0x8b, 0xc4, 0xca, 0xb2, - 0xeb, 0xa5, 0xaf, 0xc5, 0xee, 0x9e, 0x85, 0xab, 0x57, 0xa7, 0x9e, 0x67, 0x88, 0x1e, 0xff, 0xc7, - 0xd9, 0x6b, 0xa9, 0xcc, 0x7f, 0xdc, 0x96, 0xba, 0xe6, 0xdc, 0x92, 0x67, 0xde, 0x49, 0x15, 0x02, - 0xe9, 0xda, 0x99, 0x02, 0xe9, 0xeb, 0xd0, 0xf6, 0xf1, 0xd0, 0x3b, 0xc2, 0x3e, 0xd3, 0x5a, 0x1a, - 0xce, 0x56, 0xf5, 0x16, 0x07, 0x52, 0x7d, 0x9d, 0xff, 0xa6, 0xe9, 0x7f, 0x97, 0x60, 0x31, 0xe6, - 0xf6, 0x99, 0x24, 0x39, 0xfb, 0x02, 0xc3, 0x53, 0x16, 0xdd, 0xc7, 0x72, 0xd1, 0x7d, 0xf7, 0xd4, - 0x8c, 0xa7, 0xb0, 0xe4, 0xbe, 0x18, 0xf6, 0x7f, 0x06, 0x0b, 0xbc, 0xc0, 0x9d, 0x73, 0x95, 0x45, - 0x0a, 0x0f, 0xcb, 0x50, 0x25, 0x9e, 0x39, 0xaa, 0x4e, 0xb2, 0x0f, 0xc6, 0xf7, 0xf4, 0x75, 0x67, - 0xee, 0x2d, 0xdb, 0xc2, 0x6d, 0x67, 0xed, 0x37, 0xca, 0x00, 0x7b, 0x27, 0xee, 0xf0, 0x0e, 0x33, - 0xf7, 0x9b, 0x50, 0x99, 0x75, 0x39, 0x8e, 0xf4, 0xa6, 0x5a, 0x4a, 0x7b, 0x16, 0xd0, 0x00, 0xa1, - 0xb4, 0x52, 0xce, 0x96, 0x56, 0xa6, 0x15, 0x45, 0xa6, 0x3b, 0xf3, 0xef, 0x42, 0x85, 0x3a, 0x65, - 0x76, 0x77, 0xac, 0xd0, 0xf9, 0x32, 0x1d, 0x80, 0x56, 0x21, 0xda, 0xdc, 0xb7, 0x5d, 0xb6, 0x7b, - 0x53, 0xc7, 0x5e, 0xd6, 0xb3, 0x60, 0xf4, 0x02, 0x74, 0x58, 0x49, 0x2d, 0xee, 0xc8, 0xb2, 0xc3, - 0x0c, 0x34, 0x1f, 0x1b, 0x34, 0x24, 0xb1, 0x01, 0xc1, 0x6b, 0xfa, 0xde, 0x78, 0x9c, 0x9a, 0x8e, - 0xd5, 0x54, 0xb2, 0x60, 0xed, 0xf3, 0x12, 0x5c, 0x22, 0xfc, 0x7d, 0x32, 0xf1, 0x7d, 0x11, 0xe5, - 0x49, 0xed, 0x0c, 0x65, 0x71, 0x67, 0xb8, 0x0d, 0x0b, 0xac, 0x70, 0x13, 0x45, 0xaa, 0x57, 0xa7, - 0x69, 0x03, 0xd3, 0x1d, 0x3d, 0xea, 0x3e, 0x6f, 0xf6, 0x2f, 0x9c, 0xbe, 0xd7, 0xe6, 0x3b, 0x7d, - 0x5f, 0xc8, 0x96, 0x77, 0x53, 0x6a, 0x55, 0x17, 0xf7, 0xb3, 0x87, 0xd0, 0xd6, 0xd3, 0xa6, 0x81, - 0x10, 0x54, 0x52, 0xd7, 0x65, 0xe9, 0x6f, 0x9a, 0xb0, 0x1b, 0x63, 0x63, 0x68, 0x85, 0x27, 0x94, - 0x9d, 0x55, 0x3d, 0xfe, 0x96, 0xdb, 0xa1, 0xf6, 0x5f, 0x0a, 0x5c, 0x8c, 0x8e, 0x67, 0xb9, 0x95, - 0x9f, 0x5f, 0xa2, 0x1b, 0xb0, 0xc2, 0x4d, 0x3a, 0x63, 0xdb, 0x2c, 0x2c, 0x5f, 0x62, 0x30, 0x71, - 0x19, 0x1b, 0xb0, 0x12, 0x52, 0xed, 0xca, 0x8e, 0x61, 0xf2, 0x5e, 0x62, 0x8d, 0xe2, 0x98, 0x22, - 0xc7, 0xe3, 0xcf, 0xb0, 0xfb, 0x5f, 0x9c, 0xb5, 0xdc, 0x48, 0xc1, 0x9d, 0x38, 0x7c, 0x95, 0xda, - 0x31, 0x5c, 0x66, 0x17, 0xd6, 0xf7, 0x45, 0x8a, 0xe6, 0x3a, 0x1d, 0x91, 0xae, 0x3b, 0xe3, 0xd3, - 0xfe, 0x48, 0x81, 0x2b, 0x53, 0x30, 0xcf, 0x93, 0x17, 0xbe, 0x27, 0xc5, 0x3e, 0x25, 0x8b, 0x17, - 0xf0, 0xb2, 0xab, 0x0f, 0x22, 0x91, 0x9f, 0x57, 0x60, 0x31, 0xd7, 0xe9, 0xcc, 0x3a, 0xf7, 0x32, - 0x20, 0x22, 0x84, 0xf8, 0x71, 0x26, 0x2d, 0x8c, 0xf0, 0x1d, 0x56, 0x75, 0x27, 0x4e, 0xfc, 0x30, - 0x73, 0xc7, 0x33, 0x31, 0xb2, 0x58, 0x6f, 0x76, 0x36, 0x12, 0x4b, 0xae, 0x32, 0xfd, 0x0d, 0x4e, - 0x8e, 0xc0, 0xb5, 0x9d, 0x89, 0xc3, 0x8e, 0x51, 0xb8, 0x94, 0xd9, 0xae, 0x49, 0x50, 0x09, 0x60, - 0x74, 0x00, 0x8b, 0xf4, 0x76, 0xe0, 0x24, 0x1c, 0x79, 0x24, 0x35, 0xa3, 0x74, 0xb1, 0xbd, 0xf9, - 0xfb, 0x85, 0x31, 0x7d, 0xc0, 0x47, 0x13, 0xe2, 0x79, 0x76, 0xe6, 0x8a, 0xd0, 0x08, 0x8f, 0xe5, - 0x0e, 0x3d, 0x27, 0xc6, 0x53, 0x3b, 0x23, 0x9e, 0x6d, 0x3e, 0x5a, 0xc4, 0x93, 0x86, 0xf6, 0x37, - 0x61, 0x45, 0xba, 0xf4, 0x59, 0x1b, 0x7d, 0x35, 0x9d, 0xc3, 0xdd, 0x85, 0x65, 0xd9, 0xaa, 0xce, - 0x31, 0x47, 0x8e, 0xe2, 0xb3, 0xcc, 0xa1, 0xfd, 0x59, 0x09, 0xda, 0x5b, 0xd8, 0xc6, 0x21, 0x7e, - 0xba, 0xa7, 0xd7, 0xb9, 0xa3, 0xf8, 0x72, 0xfe, 0x28, 0x3e, 0x77, 0xaf, 0xa0, 0x22, 0xb9, 0x57, - 0x70, 0x25, 0xbe, 0x4e, 0x41, 0x66, 0xa9, 0x8a, 0x31, 0x84, 0x89, 0x5e, 0x87, 0xd6, 0xd8, 0xb7, - 0x1c, 0xc3, 0x3f, 0x19, 0x3c, 0xc2, 0x27, 0x01, 0xdf, 0x34, 0x7a, 0xd2, 0x6d, 0x67, 0x7b, 0x2b, - 0xd0, 0x9b, 0xbc, 0xf7, 0xbb, 0xf8, 0x84, 0x5e, 0xd5, 0x88, 0x13, 0x42, 0x76, 0x9f, 0xaf, 0xa2, - 0xa7, 0x20, 0x37, 0x5e, 0x82, 0x46, 0x7c, 0x05, 0x0a, 0xd5, 0xa1, 0x72, 0x6f, 0x62, 0xdb, 0xea, - 0x05, 0xd4, 0x80, 0x2a, 0x4d, 0x19, 0x55, 0x85, 0xfc, 0xa4, 0xb1, 0x9f, 0x5a, 0xba, 0xf1, 0xff, - 0xa0, 0x11, 0x5f, 0xc5, 0x40, 0x4d, 0x58, 0x78, 0xe8, 0xbe, 0xeb, 0x7a, 0xc7, 0xae, 0x7a, 0x01, - 0x2d, 0x40, 0xf9, 0x8e, 0x6d, 0xab, 0x0a, 0x6a, 0x43, 0x63, 0x2f, 0xf4, 0xb1, 0x41, 0xc4, 0xa7, - 0x96, 0x50, 0x07, 0xe0, 0x1d, 0x2b, 0x08, 0x3d, 0xdf, 0x1a, 0x1a, 0xb6, 0x5a, 0xbe, 0xf1, 0x19, - 0x74, 0xc4, 0xca, 0x3c, 0x6a, 0x41, 0x7d, 0xc7, 0x0b, 0xdf, 0xfe, 0xd4, 0x0a, 0x42, 0xf5, 0x02, - 0xe9, 0xbf, 0xe3, 0x85, 0xbb, 0x3e, 0x0e, 0xb0, 0x1b, 0xaa, 0x0a, 0x02, 0xa8, 0x7d, 0xe0, 0x6e, - 0x59, 0xc1, 0x23, 0xb5, 0x84, 0x96, 0xf8, 0xa1, 0x9b, 0x61, 0x6f, 0xf3, 0x72, 0xb7, 0x5a, 0x26, - 0xc3, 0xe3, 0xaf, 0x0a, 0x52, 0xa1, 0x15, 0x77, 0xb9, 0xbf, 0xfb, 0x50, 0xad, 0x32, 0xea, 0xc9, - 0xcf, 0xda, 0x0d, 0x13, 0xd4, 0xec, 0x61, 0x31, 0x99, 0x93, 0x2d, 0x22, 0x06, 0xa9, 0x17, 0xc8, - 0xca, 0xf8, 0x69, 0xbd, 0xaa, 0xa0, 0x2e, 0x34, 0x53, 0x67, 0xdf, 0x6a, 0x89, 0x00, 0xee, 0xfb, - 0xe3, 0x21, 0xd7, 0x2d, 0x46, 0x02, 0x51, 0xd4, 0x2d, 0xc2, 0x89, 0xca, 0x8d, 0xbb, 0x50, 0x8f, - 0x32, 0x1d, 0xd2, 0x95, 0xb3, 0x88, 0x7c, 0xaa, 0x17, 0xd0, 0x22, 0xb4, 0x85, 0x87, 0x7f, 0xaa, - 0x82, 0x10, 0x74, 0xc4, 0xa7, 0xb9, 0x6a, 0xe9, 0xc6, 0x06, 0x40, 0x92, 0x0c, 0x10, 0x72, 0xb6, - 0xdd, 0x23, 0xc3, 0xb6, 0x4c, 0x46, 0x1b, 0x69, 0x22, 0xdc, 0xa5, 0xdc, 0x61, 0x36, 0xab, 0x96, - 0x6e, 0xbc, 0x09, 0xf5, 0x28, 0x76, 0x25, 0x70, 0x1d, 0x3b, 0xde, 0x11, 0x66, 0x92, 0xd9, 0xc3, - 0x21, 0x93, 0xe3, 0x1d, 0x07, 0xbb, 0xa6, 0x5a, 0x22, 0x64, 0x3c, 0x1c, 0x9b, 0x46, 0x18, 0x5d, - 0x72, 0x55, 0xcb, 0x1b, 0xff, 0xbe, 0x04, 0xc0, 0x4e, 0x7f, 0x3d, 0xcf, 0x37, 0x91, 0x4d, 0x6f, - 0x81, 0x6c, 0x7a, 0xce, 0xd8, 0x73, 0xa3, 0xa3, 0xa9, 0x00, 0xad, 0x65, 0x8a, 0x2d, 0xec, 0x23, - 0xdf, 0x91, 0xf3, 0xa6, 0xff, 0x9c, 0xb4, 0x7f, 0xa6, 0xb3, 0x76, 0x01, 0x39, 0x14, 0x1b, 0xc9, - 0x37, 0x1e, 0x58, 0xc3, 0x47, 0xf1, 0x91, 0xf1, 0xf4, 0x27, 0xb3, 0x99, 0xae, 0x11, 0xbe, 0xeb, - 0x52, 0x7c, 0x7b, 0xa1, 0x6f, 0xb9, 0xa3, 0x68, 0x77, 0xd4, 0x2e, 0xa0, 0xc7, 0x99, 0x07, 0xbb, - 0x11, 0xc2, 0x8d, 0x22, 0x6f, 0x74, 0xcf, 0x87, 0xd2, 0x86, 0x6e, 0xe6, 0x9f, 0x11, 0xd0, 0x0d, - 0xf9, 0xcb, 0x27, 0xd9, 0xbf, 0x38, 0xf4, 0x5f, 0x2a, 0xd4, 0x37, 0xc6, 0x66, 0x41, 0x47, 0x7c, - 0xd2, 0x8f, 0xbe, 0x35, 0x6d, 0x82, 0xdc, 0xdb, 0xcb, 0xfe, 0x8d, 0x22, 0x5d, 0x63, 0x54, 0x1f, - 0x31, 0xf5, 0x9d, 0x85, 0x4a, 0xfa, 0xdc, 0xb5, 0x7f, 0x5a, 0x60, 0xa2, 0x5d, 0x40, 0x9f, 0x90, - 0x18, 0x22, 0xf3, 0x42, 0x14, 0xbd, 0x2c, 0xdf, 0xf7, 0xe4, 0x0f, 0x49, 0x67, 0x61, 0xf8, 0x28, - 0x6b, 0x7c, 0xd3, 0xa9, 0xcf, 0x3d, 0x3d, 0x2f, 0x4e, 0x7d, 0x6a, 0xfa, 0xd3, 0xa8, 0x3f, 0x33, - 0x06, 0x9b, 0xa5, 0x53, 0x92, 0xb7, 0x69, 0x59, 0x55, 0x4e, 0xb2, 0x99, 0xe9, 0x0f, 0xd9, 0x66, - 0x61, 0x9b, 0x50, 0x23, 0xcd, 0x5e, 0x7b, 0x78, 0x65, 0xca, 0x81, 0x8a, 0xfc, 0x51, 0x6c, 0x7f, - 0xad, 0x68, 0xf7, 0xb4, 0x2e, 0x8b, 0xef, 0x2e, 0xe5, 0x22, 0x92, 0xbe, 0x15, 0x95, 0xeb, 0xb2, - 0xfc, 0x19, 0xa7, 0x76, 0x01, 0x3d, 0x10, 0x5c, 0x3d, 0x7a, 0x61, 0x9a, 0x2a, 0x88, 0xf7, 0xa0, - 0x66, 0xf1, 0xed, 0x97, 0x01, 0x31, 0x4b, 0x75, 0x0f, 0xac, 0xd1, 0xc4, 0x37, 0x98, 0x1a, 0x4f, - 0x73, 0x6e, 0xf9, 0xae, 0x11, 0x9a, 0x6f, 0x9f, 0x61, 0x44, 0xbc, 0xa4, 0x01, 0xc0, 0x7d, 0x1c, - 0xbe, 0x4f, 0x1f, 0xe0, 0x05, 0xd9, 0x15, 0x25, 0xfe, 0x9b, 0x77, 0x88, 0x50, 0xbd, 0x38, 0xb3, - 0x5f, 0x8c, 0x60, 0x1f, 0x9a, 0xf7, 0x49, 0x7e, 0x45, 0x63, 0xc6, 0x00, 0x4d, 0x1d, 0x19, 0xf5, - 0x88, 0x50, 0xac, 0xce, 0xee, 0x98, 0x76, 0x9e, 0x99, 0x37, 0xa8, 0x68, 0xaa, 0x60, 0xf3, 0x2f, - 0x63, 0xe5, 0xce, 0x73, 0xca, 0xa3, 0x56, 0xb6, 0x22, 0x7a, 0xa8, 0xf7, 0x0e, 0x36, 0xec, 0xf0, - 0x70, 0xca, 0x8a, 0x52, 0x3d, 0x4e, 0x5f, 0x91, 0xd0, 0x31, 0xc6, 0x81, 0x61, 0x89, 0x59, 0xa1, - 0x98, 0x98, 0xae, 0xcb, 0xa7, 0xc8, 0xf7, 0x2c, 0xa8, 0x7a, 0x06, 0x2c, 0x6e, 0xf9, 0xde, 0x58, - 0x44, 0xf2, 0x8a, 0x14, 0x49, 0xae, 0x5f, 0x41, 0x14, 0x3f, 0x84, 0x56, 0x94, 0xff, 0xd3, 0x8c, - 0x45, 0xce, 0x85, 0x74, 0x97, 0x82, 0x13, 0x7f, 0x0c, 0xdd, 0x4c, 0x61, 0x41, 0x2e, 0x74, 0x79, - 0xf5, 0x61, 0xd6, 0xec, 0xc7, 0x80, 0xe8, 0xc3, 0x62, 0xf1, 0xbf, 0x11, 0xe4, 0xf1, 0x4d, 0xbe, - 0x63, 0x84, 0x64, 0xbd, 0x70, 0xff, 0x58, 0xf2, 0xbf, 0x02, 0x2b, 0xd2, 0xe4, 0x3d, 0xeb, 0x10, - 0xf8, 0xc5, 0xe7, 0x53, 0x2a, 0x0c, 0x59, 0x87, 0x70, 0xea, 0x88, 0x08, 0xff, 0xc6, 0xbf, 0x22, - 0x68, 0xd0, 0x38, 0x8f, 0x4a, 0xeb, 0xff, 0xc2, 0xbc, 0x27, 0x1b, 0xe6, 0x7d, 0x0c, 0xdd, 0xcc, - 0x83, 0x57, 0xb9, 0xd2, 0xca, 0x5f, 0xc5, 0x16, 0x88, 0x56, 0xc4, 0xb7, 0xa2, 0xf2, 0xad, 0x50, - 0xfa, 0x9e, 0x74, 0xd6, 0xdc, 0x1f, 0xb2, 0xc7, 0xe4, 0xf1, 0xb9, 0xf0, 0x8b, 0x53, 0x4f, 0x28, - 0xc4, 0x0b, 0xcc, 0x5f, 0x7e, 0x14, 0xf4, 0xf5, 0x8e, 0x40, 0x3f, 0x86, 0x6e, 0xe6, 0x89, 0x90, - 0x5c, 0x63, 0xe4, 0xef, 0x88, 0x66, 0xcd, 0xfe, 0x05, 0x06, 0x4f, 0x26, 0x2c, 0x49, 0x5e, 0x64, - 0xa0, 0xb5, 0x69, 0x81, 0xa8, 0xfc, 0xe9, 0xc6, 0xec, 0x05, 0xb5, 0x05, 0x33, 0xcd, 0xee, 0x37, - 0x09, 0x91, 0xd9, 0x3f, 0x55, 0xea, 0xbf, 0x5c, 0xec, 0x1f, 0x98, 0xe2, 0x05, 0xed, 0x41, 0x8d, - 0x3d, 0x1c, 0x42, 0xcf, 0xca, 0x0f, 0x61, 0x52, 0x8f, 0x8a, 0xfa, 0xb3, 0x9e, 0x1e, 0x05, 0x13, - 0x3b, 0x24, 0xf4, 0xff, 0x08, 0x3a, 0x0c, 0x14, 0x33, 0xe8, 0x09, 0x4e, 0xbe, 0x07, 0x55, 0xea, - 0xda, 0x91, 0xf4, 0x40, 0x21, 0xfd, 0x3c, 0xa8, 0x3f, 0xfb, 0x45, 0x50, 0x42, 0x71, 0x93, 0x8e, - 0x64, 0x55, 0x9d, 0x27, 0x39, 0xf5, 0x4d, 0x05, 0xfd, 0x08, 0xda, 0x6c, 0xf2, 0x88, 0x1b, 0x4f, - 0x92, 0xf2, 0x21, 0x2c, 0xa5, 0x28, 0x7f, 0x1a, 0x28, 0x6e, 0x2a, 0xff, 0xcb, 0xa3, 0xfb, 0x4f, - 0xe9, 0xf3, 0x9c, 0xec, 0x05, 0x34, 0xb4, 0x76, 0xb6, 0x5b, 0x74, 0xfd, 0xf5, 0xc2, 0xfd, 0x63, - 0xcc, 0x3f, 0x01, 0x35, 0x7b, 0x54, 0x88, 0x5e, 0x9a, 0xe6, 0x4b, 0x64, 0x38, 0x67, 0x38, 0x92, - 0x1f, 0x40, 0x8d, 0xd5, 0x88, 0xe5, 0x06, 0x28, 0xd4, 0x8f, 0x67, 0xcc, 0x75, 0xf7, 0x3b, 0x1f, - 0x6d, 0x8c, 0xac, 0xf0, 0x70, 0xb2, 0x4f, 0x5a, 0xd6, 0x59, 0xd7, 0x57, 0x2c, 0x8f, 0xff, 0x5a, - 0x8f, 0x64, 0xb9, 0x4e, 0x47, 0xaf, 0x53, 0x04, 0xe3, 0xfd, 0xfd, 0x1a, 0xfd, 0xbc, 0xf5, 0x3f, - 0x01, 0x00, 0x00, 0xff, 0xff, 0x83, 0xe6, 0x60, 0xbe, 0x4e, 0x54, 0x00, 0x00, + 0x7a, 0xb8, 0xe6, 0xc9, 0x99, 0x6f, 0x1e, 0x6c, 0x16, 0x49, 0x69, 0x76, 0x56, 0x92, 0xe5, 0x96, + 0x1f, 0x5c, 0xd9, 0xa6, 0xb4, 0xd4, 0xda, 0xab, 0x5d, 0xdb, 0xf0, 0x4f, 0x22, 0x2d, 0x99, 0x6b, + 0x99, 0xd6, 0xaf, 0x29, 0x79, 0x03, 0xaf, 0x77, 0xc7, 0xcd, 0xe9, 0xe2, 0xb0, 0xa1, 0x7e, 0x8c, + 0xba, 0x7b, 0x48, 0xd3, 0x01, 0x82, 0x1c, 0x72, 0xc9, 0x26, 0x1b, 0x04, 0xc9, 0x21, 0x39, 0x04, + 0x39, 0x24, 0x08, 0xb0, 0x79, 0x5d, 0x82, 0x04, 0xc8, 0x21, 0x87, 0xdc, 0x92, 0x4b, 0x5e, 0xff, + 0x43, 0x72, 0xcb, 0x75, 0x11, 0x18, 0xc8, 0x21, 0xa8, 0x57, 0x77, 0x57, 0x77, 0x0d, 0xa7, 0xc9, + 0x91, 0x5f, 0x41, 0x6e, 0xd3, 0x5f, 0x3d, 0xbe, 0xaf, 0xbe, 0x57, 0x7d, 0xdf, 0x57, 0x55, 0x03, + 0x4b, 0x4f, 0x26, 0x38, 0x38, 0x1e, 0x0c, 0x7d, 0x3f, 0xb0, 0xd6, 0xc7, 0x81, 0x1f, 0xf9, 0x08, + 0xb9, 0xb6, 0x73, 0x38, 0x09, 0xd9, 0xd7, 0x3a, 0x6d, 0xef, 0xb7, 0x87, 0xbe, 0xeb, 0xfa, 0x1e, + 0x83, 0xf5, 0xdb, 0xe9, 0x1e, 0xfd, 0xae, 0xed, 0x45, 0x38, 0xf0, 0x4c, 0x47, 0xb4, 0x86, 0xc3, + 0x03, 0xec, 0x9a, 0xfc, 0xab, 0xe9, 0x86, 0x23, 0xfe, 0x53, 0xb3, 0xcc, 0xc8, 0x4c, 0xa3, 0xea, + 0x2f, 0xd9, 0x9e, 0x85, 0x3f, 0x49, 0x83, 0xf4, 0x5f, 0x2b, 0xc1, 0xf9, 0xdd, 0x03, 0xff, 0x68, + 0xd3, 0x77, 0x1c, 0x3c, 0x8c, 0x6c, 0xdf, 0x0b, 0x0d, 0xfc, 0x64, 0x82, 0xc3, 0x08, 0xdd, 0x80, + 0xea, 0x9e, 0x19, 0xe2, 0x5e, 0xe9, 0x4a, 0x69, 0xad, 0xb5, 0x71, 0x71, 0x5d, 0xa2, 0x93, 0x13, + 0xf8, 0x5e, 0x38, 0xba, 0x63, 0x86, 0xd8, 0xa0, 0x3d, 0x11, 0x82, 0xaa, 0xb5, 0xb7, 0xbd, 0xd5, + 0x2b, 0x5f, 0x29, 0xad, 0x55, 0x0c, 0xfa, 0x1b, 0x3d, 0x07, 0x9d, 0x61, 0x3c, 0xf7, 0xf6, 0x56, + 0xd8, 0xab, 0x5c, 0xa9, 0xac, 0x55, 0x0c, 0x19, 0xa8, 0xff, 0xb4, 0x0c, 0x17, 0x72, 0x64, 0x84, + 0x63, 0xdf, 0x0b, 0x31, 0xba, 0x09, 0xf5, 0x30, 0x32, 0xa3, 0x49, 0xc8, 0x29, 0xf9, 0xa6, 0x92, + 0x92, 0x5d, 0xda, 0xc5, 0xe0, 0x5d, 0xf3, 0x68, 0xcb, 0x0a, 0xb4, 0xe8, 0xdb, 0xb0, 0x62, 0x7b, + 0xef, 0x61, 0xd7, 0x0f, 0x8e, 0x07, 0x63, 0x1c, 0x0c, 0xb1, 0x17, 0x99, 0x23, 0x2c, 0x68, 0x5c, + 0x16, 0x6d, 0x0f, 0x92, 0x26, 0xf4, 0x1a, 0x5c, 0x60, 0x32, 0x0c, 0x71, 0x70, 0x68, 0x0f, 0xf1, + 0xc0, 0x3c, 0x34, 0x6d, 0xc7, 0xdc, 0x73, 0x70, 0xaf, 0x7a, 0xa5, 0xb2, 0xd6, 0x30, 0x56, 0x69, + 0xf3, 0x2e, 0x6b, 0xbd, 0x2d, 0x1a, 0xd1, 0xb7, 0x40, 0x0b, 0xf0, 0x7e, 0x80, 0xc3, 0x83, 0xc1, + 0x38, 0xf0, 0x47, 0x01, 0x0e, 0xc3, 0x5e, 0x8d, 0xa2, 0x59, 0xe4, 0xf0, 0x07, 0x1c, 0xac, 0xff, + 0x49, 0x09, 0x56, 0x09, 0x33, 0x1e, 0x98, 0x41, 0x64, 0x7f, 0x0e, 0x22, 0xd1, 0xa1, 0x9d, 0x66, + 0x43, 0xaf, 0x42, 0xdb, 0x24, 0x18, 0xe9, 0x33, 0x16, 0xe8, 0x09, 0xfb, 0xaa, 0x94, 0x54, 0x09, + 0xa6, 0xff, 0x0b, 0xd7, 0x9d, 0x34, 0x9d, 0xf3, 0xc8, 0x2c, 0x8b, 0xb3, 0x9c, 0xc7, 0x79, 0x16, + 0x89, 0xa9, 0x38, 0x5f, 0x55, 0x73, 0xfe, 0x9f, 0x2a, 0xb0, 0x7a, 0xdf, 0x37, 0xad, 0x44, 0x0d, + 0xbf, 0x78, 0xce, 0xbf, 0x09, 0x75, 0x66, 0xd1, 0xbd, 0x2a, 0xc5, 0xf5, 0xbc, 0x8c, 0x8b, 0x5b, + 0x7b, 0x42, 0xe1, 0x2e, 0x05, 0x18, 0x7c, 0x10, 0x7a, 0x1e, 0xba, 0x01, 0x1e, 0x3b, 0xf6, 0xd0, + 0x1c, 0x78, 0x13, 0x77, 0x0f, 0x07, 0xbd, 0xda, 0x95, 0xd2, 0x5a, 0xcd, 0xe8, 0x70, 0xe8, 0x0e, + 0x05, 0xa2, 0x8f, 0xa1, 0xb3, 0x6f, 0x63, 0xc7, 0x1a, 0x50, 0x97, 0xb0, 0xbd, 0xd5, 0xab, 0x5f, + 0xa9, 0xac, 0xb5, 0x36, 0x5e, 0x5f, 0xcf, 0x7b, 0xa3, 0x75, 0x25, 0x47, 0xd6, 0xef, 0x92, 0xe1, + 0xdb, 0x6c, 0xf4, 0xdb, 0x5e, 0x14, 0x1c, 0x1b, 0xed, 0xfd, 0x14, 0x08, 0xf5, 0x60, 0x81, 0xb3, + 0xb7, 0xb7, 0x70, 0xa5, 0xb4, 0xd6, 0x30, 0xc4, 0x27, 0x7a, 0x11, 0x16, 0x03, 0x1c, 0xfa, 0x93, + 0x60, 0x88, 0x07, 0xa3, 0xc0, 0x9f, 0x8c, 0xc3, 0x5e, 0xe3, 0x4a, 0x65, 0xad, 0x69, 0x74, 0x05, + 0xf8, 0x1e, 0x85, 0xf6, 0xdf, 0x82, 0xa5, 0x1c, 0x16, 0xa4, 0x41, 0xe5, 0x31, 0x3e, 0xa6, 0x82, + 0xa8, 0x18, 0xe4, 0x27, 0x5a, 0x81, 0xda, 0xa1, 0xe9, 0x4c, 0x30, 0x67, 0x35, 0xfb, 0xf8, 0x7e, + 0xf9, 0x56, 0x49, 0xff, 0x83, 0x12, 0xf4, 0x0c, 0xec, 0x60, 0x33, 0xc4, 0x5f, 0xa6, 0x48, 0xcf, + 0x43, 0xdd, 0xf3, 0x2d, 0xbc, 0xbd, 0x45, 0x45, 0x5a, 0x31, 0xf8, 0x97, 0xfe, 0x59, 0x09, 0x56, + 0xee, 0xe1, 0x88, 0x98, 0x81, 0x1d, 0x46, 0xf6, 0x30, 0xb6, 0xf3, 0x37, 0xa1, 0x12, 0xe0, 0x27, + 0x9c, 0xb2, 0x97, 0x64, 0xca, 0x62, 0xf7, 0xaf, 0x1a, 0x69, 0x90, 0x71, 0xe8, 0x59, 0x68, 0x5b, + 0xae, 0x33, 0x18, 0x1e, 0x98, 0x9e, 0x87, 0x1d, 0x66, 0x48, 0x4d, 0xa3, 0x65, 0xb9, 0xce, 0x26, + 0x07, 0xa1, 0xcb, 0x00, 0x21, 0x1e, 0xb9, 0xd8, 0x8b, 0x12, 0x9f, 0x9c, 0x82, 0xa0, 0x6b, 0xb0, + 0xb4, 0x1f, 0xf8, 0xee, 0x20, 0x3c, 0x30, 0x03, 0x6b, 0xe0, 0x60, 0xd3, 0xc2, 0x01, 0xa5, 0xbe, + 0x61, 0x2c, 0x92, 0x86, 0x5d, 0x02, 0xbf, 0x4f, 0xc1, 0xe8, 0x26, 0xd4, 0xc2, 0xa1, 0x3f, 0xc6, + 0x54, 0xd3, 0xba, 0x1b, 0x97, 0x54, 0x3a, 0xb4, 0x65, 0x46, 0xe6, 0x2e, 0xe9, 0x64, 0xb0, 0xbe, + 0xfa, 0xdf, 0x56, 0x99, 0xa9, 0x7d, 0xc5, 0x9d, 0x5c, 0xca, 0x1c, 0x6b, 0x4f, 0xc7, 0x1c, 0xeb, + 0x85, 0xcc, 0x71, 0xe1, 0x64, 0x73, 0xcc, 0x71, 0xed, 0x34, 0xe6, 0xd8, 0x98, 0x69, 0x8e, 0x4d, + 0x95, 0x39, 0xa2, 0xb7, 0x61, 0x91, 0x05, 0x10, 0xb6, 0xb7, 0xef, 0x0f, 0x1c, 0x3b, 0x8c, 0x7a, + 0x40, 0xc9, 0xbc, 0x94, 0xd5, 0x50, 0x0b, 0x7f, 0xb2, 0xce, 0x10, 0x7b, 0xfb, 0xbe, 0xd1, 0xb1, + 0xc5, 0xcf, 0xfb, 0x76, 0x18, 0xcd, 0x6f, 0xd5, 0x7f, 0x9f, 0x58, 0xf5, 0x57, 0x5d, 0x7b, 0x12, + 0xcb, 0xaf, 0x49, 0x96, 0xff, 0xa7, 0x25, 0xf8, 0xc6, 0x3d, 0x1c, 0xc5, 0xe4, 0x13, 0x43, 0xc6, + 0x5f, 0xd1, 0x6d, 0xfe, 0x2f, 0x4b, 0xd0, 0x57, 0xd1, 0x3a, 0xcf, 0x56, 0xff, 0x21, 0x9c, 0x8f, + 0x71, 0x0c, 0x2c, 0x1c, 0x0e, 0x03, 0x7b, 0x4c, 0xc5, 0x48, 0x7d, 0x55, 0x6b, 0xe3, 0xaa, 0x4a, + 0xf1, 0xb3, 0x14, 0xac, 0xc6, 0x53, 0x6c, 0xa5, 0x66, 0xd0, 0x7f, 0x56, 0x82, 0x55, 0xe2, 0x1b, + 0xb9, 0x33, 0x23, 0x1a, 0x78, 0x66, 0xbe, 0xca, 0x6e, 0xb2, 0x9c, 0x73, 0x93, 0x05, 0x78, 0x4c, + 0x43, 0xec, 0x2c, 0x3d, 0xf3, 0xf0, 0xee, 0x55, 0xa8, 0x11, 0x03, 0x14, 0xac, 0x7a, 0x46, 0xc5, + 0xaa, 0x34, 0x32, 0xd6, 0x5b, 0xf7, 0x18, 0x15, 0x89, 0xdf, 0x9e, 0x43, 0xdd, 0xb2, 0xcb, 0x2e, + 0x2b, 0x96, 0xfd, 0x9b, 0x25, 0xb8, 0x90, 0x43, 0x38, 0xcf, 0xba, 0xdf, 0x80, 0x3a, 0xdd, 0x8d, + 0xc4, 0xc2, 0x9f, 0x53, 0x2e, 0x3c, 0x85, 0x8e, 0x78, 0x1b, 0x83, 0x8f, 0xd1, 0x7d, 0xd0, 0xb2, + 0x6d, 0x64, 0x9f, 0xe4, 0x7b, 0xe4, 0xc0, 0x33, 0x5d, 0xc6, 0x80, 0xa6, 0xd1, 0xe2, 0xb0, 0x1d, + 0xd3, 0xc5, 0xe8, 0x1b, 0xd0, 0x20, 0x26, 0x3b, 0xb0, 0x2d, 0x21, 0xfe, 0x05, 0x6a, 0xc2, 0x56, + 0x88, 0x2e, 0x01, 0xd0, 0x26, 0xd3, 0xb2, 0x02, 0xb6, 0x85, 0x36, 0x8d, 0x26, 0x81, 0xdc, 0x26, + 0x00, 0xfd, 0xf7, 0x4b, 0x70, 0x79, 0xf7, 0xd8, 0x1b, 0xee, 0xe0, 0xa3, 0xcd, 0x00, 0x9b, 0x11, + 0x4e, 0x9c, 0xf6, 0xe7, 0xca, 0x78, 0x74, 0x05, 0x5a, 0x29, 0xfb, 0xe5, 0x2a, 0x99, 0x06, 0xe9, + 0x7f, 0x55, 0x82, 0x36, 0xd9, 0x45, 0xde, 0xc3, 0x91, 0x49, 0x54, 0x04, 0x7d, 0x0f, 0x9a, 0x8e, + 0x6f, 0x5a, 0x83, 0xe8, 0x78, 0xcc, 0xa8, 0xe9, 0x66, 0xa9, 0x49, 0xb6, 0x9e, 0x87, 0xc7, 0x63, + 0x6c, 0x34, 0x1c, 0xfe, 0xab, 0x10, 0x45, 0x59, 0x2f, 0x53, 0x51, 0x78, 0xca, 0x67, 0xa0, 0xe5, + 0xe2, 0x28, 0xb0, 0x87, 0x8c, 0x88, 0x2a, 0x15, 0x05, 0x30, 0x10, 0x41, 0xa4, 0xff, 0xac, 0x0e, + 0xe7, 0x7f, 0x68, 0x46, 0xc3, 0x83, 0x2d, 0x57, 0x44, 0x31, 0x67, 0xe7, 0x63, 0xe2, 0x97, 0xcb, + 0x69, 0xbf, 0xfc, 0xd4, 0xfc, 0x7e, 0x6c, 0xa3, 0x35, 0x95, 0x8d, 0x92, 0xc4, 0x7c, 0xfd, 0x03, + 0xae, 0x66, 0x29, 0x1b, 0x4d, 0x05, 0x1b, 0xf5, 0xb3, 0x04, 0x1b, 0x9b, 0xd0, 0xc1, 0x9f, 0x0c, + 0x9d, 0x09, 0xd1, 0x57, 0x8a, 0x9d, 0x45, 0x11, 0x97, 0x15, 0xd8, 0xd3, 0x0e, 0xa2, 0xcd, 0x07, + 0x6d, 0x73, 0x1a, 0x98, 0x2e, 0xb8, 0x38, 0x32, 0x69, 0xa8, 0xd0, 0xda, 0xb8, 0x32, 0x4d, 0x17, + 0x84, 0x02, 0x31, 0x7d, 0x20, 0x5f, 0xe8, 0x22, 0x34, 0x79, 0x68, 0xb3, 0xbd, 0xd5, 0x6b, 0x52, + 0xf6, 0x25, 0x00, 0x64, 0x42, 0x87, 0x7b, 0x4f, 0x4e, 0x21, 0x0b, 0x20, 0xde, 0x50, 0x21, 0x50, + 0x0b, 0x3b, 0x4d, 0x79, 0xc8, 0x03, 0x9d, 0x30, 0x05, 0x22, 0x99, 0xbf, 0xbf, 0xbf, 0xef, 0xd8, + 0x1e, 0xde, 0x61, 0x12, 0x6e, 0x51, 0x22, 0x64, 0x20, 0x09, 0x87, 0x0e, 0x71, 0x10, 0xda, 0xbe, + 0xd7, 0x6b, 0xd3, 0x76, 0xf1, 0xa9, 0x8a, 0x72, 0x3a, 0x67, 0x88, 0x72, 0x06, 0xb0, 0x94, 0xa3, + 0x54, 0x11, 0xe5, 0x7c, 0x27, 0x1d, 0xe5, 0xcc, 0x16, 0x55, 0x2a, 0x0a, 0xfa, 0x79, 0x09, 0x56, + 0x1f, 0x79, 0xe1, 0x64, 0x2f, 0x66, 0xd1, 0x97, 0x63, 0x0e, 0x59, 0x27, 0x5a, 0xcd, 0x39, 0x51, + 0xfd, 0xcf, 0xeb, 0xb0, 0xc8, 0x57, 0x41, 0xb4, 0x86, 0xba, 0x9c, 0x8b, 0xd0, 0x8c, 0xf7, 0x51, + 0xce, 0x90, 0x04, 0x90, 0xf5, 0x61, 0xe5, 0x9c, 0x0f, 0x2b, 0x44, 0x9a, 0x88, 0x8a, 0xaa, 0xa9, + 0xa8, 0xe8, 0x12, 0xc0, 0xbe, 0x33, 0x09, 0x0f, 0x06, 0x91, 0xed, 0x62, 0x1e, 0x95, 0x35, 0x29, + 0xe4, 0xa1, 0xed, 0x62, 0x74, 0x1b, 0xda, 0x7b, 0xb6, 0xe7, 0xf8, 0xa3, 0xc1, 0xd8, 0x8c, 0x0e, + 0x42, 0x9e, 0x16, 0xab, 0xc4, 0x42, 0x63, 0xd8, 0x3b, 0xb4, 0xaf, 0xd1, 0x62, 0x63, 0x1e, 0x90, + 0x21, 0xe8, 0x32, 0xb4, 0xbc, 0x89, 0x3b, 0xf0, 0xf7, 0x07, 0x81, 0x7f, 0x14, 0xd2, 0xe4, 0xb7, + 0x62, 0x34, 0xbd, 0x89, 0xfb, 0xfe, 0xbe, 0xe1, 0x1f, 0x91, 0x7d, 0xac, 0x49, 0x76, 0xb4, 0xd0, + 0xf1, 0x47, 0x2c, 0xf1, 0x9d, 0x3d, 0x7f, 0x32, 0x80, 0x8c, 0xb6, 0xb0, 0x13, 0x99, 0x74, 0x74, + 0xb3, 0xd8, 0xe8, 0x78, 0x00, 0x7a, 0x01, 0xba, 0x43, 0xdf, 0x1d, 0x9b, 0x94, 0x43, 0x77, 0x03, + 0xdf, 0xa5, 0x06, 0x58, 0x31, 0x32, 0x50, 0xb4, 0x09, 0xad, 0xc4, 0x08, 0xc2, 0x5e, 0x8b, 0xe2, + 0xd1, 0x55, 0x56, 0x9a, 0x0a, 0xe5, 0x89, 0x82, 0x42, 0x6c, 0x05, 0x21, 0xd1, 0x0c, 0x61, 0xec, + 0xa1, 0xfd, 0x29, 0xe6, 0x86, 0xd6, 0xe2, 0xb0, 0x5d, 0xfb, 0x53, 0x4c, 0xd2, 0x23, 0xdb, 0x0b, + 0x71, 0x10, 0x89, 0x64, 0xb5, 0xd7, 0xa1, 0xea, 0xd3, 0x61, 0x50, 0xae, 0xd8, 0x68, 0x0b, 0xba, + 0x61, 0x64, 0x06, 0xd1, 0x60, 0xec, 0x87, 0x54, 0x01, 0x7a, 0x5d, 0xaa, 0xdb, 0x19, 0x93, 0x74, + 0xc3, 0x11, 0x51, 0xec, 0x07, 0xbc, 0x93, 0xd1, 0xa1, 0x83, 0xc4, 0x27, 0x99, 0x85, 0x72, 0x22, + 0x99, 0x65, 0xb1, 0xd0, 0x2c, 0x74, 0x50, 0x3c, 0xcb, 0x1a, 0x49, 0x97, 0x4c, 0xcb, 0xdc, 0x73, + 0xf0, 0x07, 0xdc, 0x83, 0x68, 0x74, 0x61, 0x59, 0x30, 0xd9, 0x04, 0x1c, 0x7c, 0x88, 0x9d, 0xde, + 0x12, 0xdd, 0x51, 0x9f, 0x99, 0x6e, 0xdb, 0xf7, 0x49, 0x37, 0x83, 0xf5, 0xd6, 0xff, 0xb8, 0x02, + 0x5d, 0x99, 0xab, 0xc4, 0x5b, 0xb1, 0x64, 0x4e, 0x98, 0x8a, 0xf8, 0x24, 0x3c, 0xc6, 0x1e, 0x41, + 0xca, 0x32, 0x47, 0x6a, 0x29, 0x0d, 0xa3, 0xc5, 0x60, 0x74, 0x02, 0xa2, 0xf1, 0x4c, 0x96, 0xd4, + 0x3c, 0x2b, 0x94, 0xbf, 0x4d, 0x0a, 0xa1, 0x11, 0x4e, 0x0f, 0x16, 0x44, 0xd2, 0xc9, 0xec, 0x44, + 0x7c, 0x92, 0x96, 0xbd, 0x89, 0x4d, 0xb1, 0x32, 0x3b, 0x11, 0x9f, 0x68, 0x0b, 0xda, 0x6c, 0xca, + 0xb1, 0x19, 0x98, 0xae, 0xb0, 0x92, 0x67, 0x95, 0x9e, 0xe6, 0x5d, 0x7c, 0xfc, 0x01, 0x71, 0x5a, + 0x0f, 0x4c, 0x3b, 0x30, 0x98, 0x56, 0x3d, 0xa0, 0xa3, 0xd0, 0x1a, 0x68, 0x6c, 0x96, 0x7d, 0xdb, + 0xc1, 0xdc, 0xde, 0x16, 0x58, 0xe6, 0x49, 0xe1, 0x77, 0x6d, 0x07, 0x33, 0x93, 0x8a, 0x97, 0x40, + 0xf5, 0xa8, 0xc1, 0x2c, 0x8a, 0x42, 0xa8, 0x16, 0x5d, 0x05, 0xe6, 0x7c, 0x07, 0xc2, 0xa5, 0xb3, + 0x7d, 0x87, 0xd1, 0x28, 0xa4, 0x41, 0x22, 0xb9, 0x89, 0xcb, 0x6c, 0x12, 0xd8, 0x72, 0xbc, 0x89, + 0x4b, 0x2d, 0x72, 0x03, 0x56, 0x87, 0x93, 0x20, 0x60, 0xbb, 0x52, 0x7a, 0x9e, 0x16, 0xcd, 0xd5, + 0x97, 0x79, 0xe3, 0x76, 0x6a, 0x3a, 0xfd, 0x77, 0x6a, 0xb0, 0x4c, 0x9c, 0x19, 0x97, 0xe0, 0x1c, + 0xb1, 0xc8, 0x25, 0x00, 0x2b, 0x8c, 0x06, 0x92, 0x03, 0x6e, 0x5a, 0x61, 0xc4, 0x77, 0xaa, 0xef, + 0x89, 0x50, 0xa2, 0x32, 0x3d, 0x33, 0xca, 0x38, 0xd7, 0x7c, 0x38, 0x71, 0xa6, 0x52, 0xe2, 0x55, + 0xe8, 0xf0, 0xb2, 0x80, 0x94, 0xc3, 0xb6, 0x19, 0x70, 0x47, 0xbd, 0x45, 0xd4, 0x95, 0x25, 0xcd, + 0x54, 0x48, 0xb1, 0x30, 0x5f, 0x48, 0xd1, 0xc8, 0x86, 0x14, 0x77, 0x61, 0x51, 0xb6, 0x6a, 0xe1, + 0x16, 0x67, 0x98, 0x75, 0x57, 0x32, 0xeb, 0x30, 0x1d, 0x11, 0x80, 0x1c, 0x11, 0x5c, 0x85, 0x8e, + 0x87, 0xb1, 0x35, 0x88, 0x02, 0xd3, 0x0b, 0xf7, 0x71, 0x40, 0xd5, 0xa2, 0x61, 0xb4, 0x09, 0xf0, + 0x21, 0x87, 0xa1, 0x37, 0x00, 0xe8, 0x1a, 0x59, 0x25, 0xac, 0x3d, 0xbd, 0x12, 0x46, 0x95, 0x86, + 0x56, 0xc2, 0x28, 0x53, 0xe8, 0xcf, 0xa7, 0x14, 0x74, 0xe8, 0xff, 0x5c, 0x86, 0xf3, 0xbc, 0x32, + 0x32, 0xbf, 0x5e, 0x4e, 0x0b, 0x0a, 0xc4, 0xae, 0x5a, 0x39, 0xa1, 0xd6, 0x50, 0x2d, 0x10, 0x37, + 0xd7, 0x14, 0x71, 0xb3, 0x9c, 0x6f, 0xd7, 0x73, 0xf9, 0x76, 0x5c, 0x6a, 0x5c, 0x28, 0x5e, 0x6a, + 0x44, 0x2b, 0x50, 0xa3, 0x49, 0x20, 0xd5, 0x9d, 0xa6, 0xc1, 0x3e, 0x0a, 0x49, 0x55, 0xff, 0xbd, + 0x32, 0x74, 0x76, 0xb1, 0x19, 0x0c, 0x0f, 0x04, 0x1f, 0x5f, 0x4b, 0x97, 0x66, 0x9f, 0x9b, 0x52, + 0x9a, 0x95, 0x86, 0x7c, 0x6d, 0x6a, 0xb2, 0x04, 0x41, 0xe4, 0x47, 0x66, 0x4c, 0xe5, 0xc0, 0x9b, + 0xb8, 0xbc, 0x5e, 0xb9, 0x48, 0x1b, 0x38, 0xa9, 0x3b, 0x13, 0x57, 0xff, 0xcf, 0x12, 0xb4, 0xff, + 0x3f, 0x99, 0x46, 0x30, 0xe6, 0x56, 0x9a, 0x31, 0x2f, 0x4c, 0x61, 0x8c, 0x41, 0xf2, 0x39, 0x7c, + 0x88, 0xbf, 0x76, 0xe5, 0xea, 0x7f, 0x28, 0x41, 0x9f, 0x64, 0xf3, 0x06, 0xf3, 0x3b, 0xf3, 0x5b, + 0xd7, 0x55, 0xe8, 0x1c, 0x4a, 0x71, 0x73, 0x99, 0x2a, 0x67, 0xfb, 0x30, 0x5d, 0x7d, 0x30, 0x40, + 0x13, 0xd5, 0x63, 0xbe, 0x58, 0xb1, 0x0d, 0xbc, 0xa8, 0xa2, 0x3a, 0x43, 0x1c, 0xf5, 0x10, 0x8b, + 0x81, 0x0c, 0xd4, 0x7f, 0xab, 0x04, 0xcb, 0x8a, 0x8e, 0xe8, 0x02, 0x2c, 0xf0, 0x4a, 0x07, 0x8f, + 0x31, 0x98, 0xbd, 0x5b, 0x44, 0x3c, 0x49, 0xad, 0xce, 0xb6, 0xf2, 0xc1, 0xb8, 0x45, 0x92, 0xf7, + 0x38, 0xad, 0xb3, 0x72, 0xf2, 0xb1, 0x42, 0xd4, 0x87, 0x06, 0xf7, 0xa6, 0x22, 0x5f, 0x8e, 0xbf, + 0xf5, 0xc7, 0x80, 0xee, 0xe1, 0x64, 0xef, 0x9a, 0x87, 0xa3, 0x89, 0xbf, 0x49, 0x08, 0x4d, 0x3b, + 0x21, 0x4b, 0xff, 0xf7, 0x12, 0x2c, 0x4b, 0xd8, 0xe6, 0xa9, 0x48, 0x25, 0xfb, 0x6b, 0xf9, 0x2c, + 0xfb, 0xab, 0x54, 0x75, 0xa9, 0x9c, 0xaa, 0xea, 0x72, 0x19, 0x20, 0xe6, 0xbf, 0xe0, 0x68, 0x0a, + 0xa2, 0xff, 0x5d, 0x09, 0xce, 0xbf, 0x63, 0x7a, 0x96, 0xbf, 0xbf, 0x3f, 0xbf, 0xaa, 0x6e, 0x82, + 0x94, 0x61, 0x17, 0xad, 0x3b, 0xca, 0x69, 0xf9, 0x4b, 0xb0, 0x14, 0xb0, 0x9d, 0xc9, 0x92, 0x75, + 0xb9, 0x62, 0x68, 0xa2, 0x21, 0xd6, 0xd1, 0xbf, 0x28, 0x03, 0x22, 0xab, 0xbe, 0x63, 0x3a, 0xa6, + 0x37, 0xc4, 0x67, 0x27, 0xfd, 0x79, 0xe8, 0x4a, 0x21, 0x4c, 0x7c, 0x0f, 0x20, 0x1d, 0xc3, 0x84, + 0xe8, 0x5d, 0xe8, 0xee, 0x31, 0x54, 0x83, 0x00, 0x9b, 0xa1, 0xef, 0x71, 0x71, 0x28, 0x4b, 0x8c, + 0x0f, 0x03, 0x7b, 0x34, 0xc2, 0xc1, 0xa6, 0xef, 0x59, 0x3c, 0x41, 0xd8, 0x13, 0x64, 0x92, 0xa1, + 0xc4, 0x18, 0x92, 0x78, 0x2e, 0x16, 0x4e, 0x1c, 0xd0, 0x51, 0x56, 0x84, 0xd8, 0x74, 0x12, 0x46, + 0x24, 0xbb, 0xa1, 0xc6, 0x1a, 0x76, 0xa7, 0x57, 0x98, 0x15, 0xf1, 0x95, 0xfe, 0xd7, 0x25, 0x40, + 0x71, 0x15, 0x80, 0x96, 0x4d, 0xa8, 0x45, 0x67, 0x87, 0x96, 0x14, 0x9b, 0xf2, 0x45, 0x68, 0x5a, + 0x62, 0x24, 0x77, 0x41, 0x09, 0x80, 0xee, 0x91, 0x94, 0xe8, 0x01, 0xd1, 0x3c, 0x6c, 0x89, 0x2c, + 0x9b, 0x01, 0xef, 0x53, 0x98, 0x1c, 0x9e, 0x55, 0xb3, 0xe1, 0x59, 0xba, 0x80, 0x5a, 0x93, 0x0a, + 0xa8, 0xfa, 0xcf, 0xcb, 0xa0, 0xd1, 0x2d, 0x64, 0x33, 0xa9, 0x84, 0x15, 0x22, 0xfa, 0x2a, 0x74, + 0xf8, 0x3d, 0x1a, 0x89, 0xf0, 0xf6, 0x93, 0xd4, 0x64, 0xe8, 0x06, 0xac, 0xb0, 0x4e, 0x01, 0x0e, + 0x27, 0x4e, 0x92, 0x60, 0xb2, 0x04, 0x08, 0x3d, 0x61, 0x7b, 0x17, 0x69, 0x12, 0x23, 0x1e, 0xc1, + 0xf9, 0x91, 0xe3, 0xef, 0x99, 0xce, 0x40, 0x16, 0x0f, 0x93, 0x61, 0x01, 0x8d, 0x5f, 0x61, 0xc3, + 0x77, 0xd3, 0x32, 0x0c, 0xd1, 0x1d, 0xe8, 0x84, 0x18, 0x3f, 0x4e, 0xb2, 0xce, 0x5a, 0x91, 0xac, + 0xb3, 0x4d, 0xc6, 0x88, 0x2f, 0xfd, 0x0f, 0x4b, 0xb0, 0x98, 0x39, 0xfe, 0xc8, 0xd6, 0x48, 0x4a, + 0xf9, 0x1a, 0xc9, 0x2d, 0xa8, 0x11, 0x4f, 0xc5, 0xf6, 0x96, 0xae, 0x3a, 0x7f, 0x97, 0x67, 0x35, + 0xd8, 0x00, 0x74, 0x1d, 0x96, 0x15, 0xd7, 0x2c, 0xb8, 0xf8, 0x51, 0xfe, 0x96, 0x85, 0xfe, 0x8b, + 0x2a, 0xb4, 0x52, 0xac, 0x98, 0x51, 0xde, 0x79, 0x2a, 0x65, 0xec, 0x69, 0xc7, 0xea, 0x44, 0xe5, + 0x5c, 0xec, 0xb2, 0x5c, 0x91, 0x27, 0xae, 0x2e, 0x76, 0x69, 0xa6, 0x98, 0x4e, 0x02, 0xeb, 0x72, + 0x12, 0x28, 0xa7, 0xc9, 0x0b, 0x27, 0xa4, 0xc9, 0x0d, 0x39, 0x4d, 0x96, 0x4c, 0xa8, 0x99, 0x35, + 0xa1, 0xa2, 0x15, 0x97, 0x1b, 0xb0, 0x3c, 0x64, 0xc7, 0x04, 0x77, 0x8e, 0x37, 0xe3, 0x26, 0x1e, + 0x94, 0xaa, 0x9a, 0xd0, 0xdd, 0xa4, 0x96, 0xca, 0xa4, 0xcc, 0x92, 0x0e, 0x75, 0x16, 0xce, 0x65, + 0xc3, 0x84, 0x2c, 0x3c, 0x33, 0xfd, 0xca, 0xd6, 0x7a, 0x3a, 0x67, 0xaa, 0xf5, 0x3c, 0x03, 0x2d, + 0x11, 0xa9, 0x10, 0x4b, 0xef, 0x32, 0xa7, 0x27, 0xdc, 0x80, 0x15, 0x4a, 0x7e, 0x60, 0x51, 0x3e, + 0x48, 0xc9, 0xd6, 0x30, 0xb4, 0x7c, 0x0d, 0xe3, 0x02, 0x2c, 0xd8, 0xe1, 0x60, 0xdf, 0x7c, 0x8c, + 0x69, 0x31, 0xa5, 0x61, 0xd4, 0xed, 0xf0, 0xae, 0xf9, 0x18, 0xeb, 0xff, 0x5a, 0x81, 0x6e, 0xb2, + 0xc1, 0x16, 0xf6, 0x20, 0x45, 0xae, 0x1a, 0xed, 0x80, 0x96, 0xc4, 0x3d, 0x94, 0xc3, 0x27, 0xe6, + 0xe0, 0xd9, 0xd3, 0xc9, 0xc5, 0x71, 0xc6, 0x5e, 0xa5, 0xed, 0xbe, 0x7a, 0xaa, 0xed, 0x7e, 0xce, + 0x4b, 0x08, 0x37, 0x61, 0x35, 0xde, 0x7b, 0xa5, 0x65, 0xb3, 0x04, 0x6b, 0x45, 0x34, 0x3e, 0x48, + 0x2f, 0x7f, 0x8a, 0x0b, 0x58, 0x98, 0xe6, 0x02, 0xb2, 0x2a, 0xd0, 0xc8, 0xa9, 0x40, 0xfe, 0x2e, + 0x44, 0x53, 0x71, 0x17, 0x42, 0x7f, 0x04, 0xcb, 0xb4, 0xae, 0x1d, 0x0e, 0x03, 0x7b, 0x0f, 0xc7, + 0x29, 0x40, 0x11, 0xb1, 0xf6, 0xa1, 0x91, 0xc9, 0x22, 0xe2, 0x6f, 0xfd, 0xa7, 0x25, 0x38, 0x9f, + 0x9f, 0x97, 0x6a, 0x4c, 0xe2, 0x48, 0x4a, 0x92, 0x23, 0xf9, 0x25, 0x58, 0x4e, 0x45, 0x94, 0xd2, + 0xcc, 0x53, 0x22, 0x70, 0x05, 0xe1, 0x06, 0x4a, 0xe6, 0x10, 0x30, 0xfd, 0x17, 0xa5, 0xf8, 0x78, + 0x80, 0xc0, 0x46, 0xf4, 0xec, 0x85, 0xec, 0x6b, 0xbe, 0xe7, 0xd8, 0x5e, 0x5c, 0x70, 0xe1, 0x6b, + 0x64, 0x40, 0x5e, 0x70, 0x79, 0x07, 0x16, 0x79, 0xa7, 0x78, 0x7b, 0x2a, 0x18, 0x90, 0x75, 0xd9, + 0xb8, 0x78, 0x63, 0x7a, 0x1e, 0xba, 0xfc, 0x50, 0x44, 0xe0, 0xab, 0xa8, 0x8e, 0x4a, 0x7e, 0x00, + 0x9a, 0xe8, 0x76, 0xda, 0x0d, 0x71, 0x91, 0x0f, 0x8c, 0x03, 0xbb, 0x5f, 0x2f, 0x41, 0x4f, 0xde, + 0x1e, 0x53, 0xcb, 0x3f, 0x7d, 0x78, 0xf7, 0xba, 0x7c, 0x14, 0xfe, 0xfc, 0x09, 0xf4, 0x24, 0x78, + 0xc4, 0x81, 0xf8, 0x6f, 0x97, 0xe9, 0xbd, 0x06, 0x92, 0xea, 0x6d, 0xd9, 0x61, 0x14, 0xd8, 0x7b, + 0x93, 0xf9, 0x0e, 0x67, 0x4d, 0x68, 0x0d, 0x0f, 0xf0, 0xf0, 0xf1, 0xd8, 0xb7, 0x13, 0xa9, 0xbc, + 0xa5, 0xa2, 0x69, 0x3a, 0xda, 0xf5, 0xcd, 0x64, 0x06, 0x76, 0xba, 0x95, 0x9e, 0xb3, 0xff, 0x63, + 0xd0, 0xb2, 0x1d, 0xd2, 0x87, 0x4a, 0x4d, 0x76, 0xa8, 0x74, 0x53, 0x3e, 0x54, 0x9a, 0x11, 0x69, + 0xa4, 0xce, 0x94, 0xfe, 0xa6, 0x0c, 0xdf, 0x54, 0xd2, 0x36, 0x4f, 0x96, 0x34, 0xad, 0x8e, 0x74, + 0x07, 0x1a, 0x99, 0xa4, 0xf6, 0x85, 0x13, 0xe4, 0xc7, 0xeb, 0xae, 0xac, 0x34, 0x18, 0x26, 0xb1, + 0x55, 0x62, 0xf0, 0xd5, 0xe9, 0x73, 0x70, 0xbb, 0x93, 0xe6, 0x10, 0xe3, 0xd0, 0x6d, 0x68, 0xb3, + 0x82, 0xc1, 0xe0, 0xd0, 0xc6, 0x47, 0xe2, 0xc8, 0xf6, 0xb2, 0xd2, 0x35, 0xd3, 0x7e, 0x1f, 0xd8, + 0xf8, 0xc8, 0x68, 0x39, 0xf1, 0xef, 0x50, 0xff, 0xdd, 0x2a, 0x40, 0xd2, 0x46, 0xb2, 0xb3, 0xc4, + 0xe6, 0xb9, 0x11, 0xa7, 0x20, 0x24, 0x96, 0x90, 0x23, 0x57, 0xf1, 0x89, 0x8c, 0xe4, 0xc8, 0xc4, + 0xb2, 0xc3, 0x88, 0xf3, 0xe5, 0xfa, 0xc9, 0xb4, 0x08, 0x16, 0x11, 0x91, 0x71, 0x9d, 0x09, 0x13, + 0x08, 0x7a, 0x05, 0xd0, 0x28, 0xf0, 0x8f, 0x6c, 0x6f, 0x94, 0xce, 0x37, 0x58, 0x5a, 0xb2, 0xc4, + 0x5b, 0x52, 0x09, 0xc7, 0x4f, 0x40, 0xcb, 0x74, 0x17, 0x2c, 0xb9, 0x39, 0x83, 0x8c, 0x7b, 0xd2, + 0x5c, 0x5c, 0x7d, 0x17, 0x65, 0x0c, 0xf4, 0x7c, 0xf6, 0xa1, 0x19, 0x8c, 0xb0, 0x90, 0x28, 0x8f, + 0xc3, 0x64, 0x60, 0x7f, 0x00, 0x5a, 0x76, 0x55, 0x8a, 0xd3, 0xd3, 0x57, 0x65, 0x45, 0x3f, 0xc9, + 0x1f, 0x91, 0x69, 0x52, 0xaa, 0xde, 0x37, 0x61, 0x45, 0x45, 0xaf, 0x02, 0xc9, 0x99, 0xad, 0xe9, + 0xad, 0x38, 0x24, 0xa6, 0x72, 0x98, 0xb6, 0xcb, 0xa4, 0x0a, 0xcf, 0x65, 0xa9, 0xf0, 0xac, 0xff, + 0x6a, 0x05, 0x50, 0x5e, 0xfd, 0x51, 0x17, 0xca, 0xf1, 0x24, 0xe5, 0xed, 0xad, 0x8c, 0xba, 0x95, + 0x73, 0xea, 0x76, 0x11, 0x9a, 0xf1, 0xae, 0xcf, 0x5d, 0x7c, 0x02, 0x48, 0x2b, 0x63, 0x55, 0x56, + 0xc6, 0x14, 0x61, 0x35, 0xb9, 0x22, 0x7e, 0x03, 0x56, 0x1c, 0x33, 0x8c, 0x06, 0xac, 0xf0, 0x1e, + 0xd9, 0x2e, 0x0e, 0x23, 0xd3, 0x1d, 0x53, 0x51, 0x56, 0x0d, 0x44, 0xda, 0xb6, 0x48, 0xd3, 0x43, + 0xd1, 0x82, 0x1e, 0x8a, 0xe8, 0x9a, 0xf8, 0x5e, 0x7e, 0x2f, 0xe1, 0xd5, 0x62, 0xe6, 0x9e, 0x94, + 0xbb, 0x99, 0x46, 0x35, 0xe3, 0xb0, 0xb3, 0xff, 0x31, 0x74, 0xe5, 0x46, 0x85, 0xf8, 0x6e, 0xc9, + 0xe2, 0x2b, 0x12, 0xd8, 0xa6, 0x64, 0x78, 0x00, 0x28, 0xef, 0x3c, 0xd2, 0x3c, 0x2b, 0xc9, 0x3c, + 0x9b, 0x25, 0x8b, 0x14, 0x4f, 0x2b, 0xb2, 0xb0, 0xff, 0xb1, 0x02, 0x28, 0x89, 0xe0, 0xe2, 0x73, + 0xf2, 0x22, 0x61, 0xcf, 0x75, 0x58, 0xce, 0xc7, 0x77, 0x22, 0xa8, 0x45, 0xb9, 0xe8, 0x4e, 0x15, + 0x89, 0x55, 0x54, 0xb7, 0x52, 0x5f, 0x8b, 0xdd, 0x3d, 0x0b, 0x57, 0x2f, 0x4f, 0x3d, 0xcf, 0x90, + 0x3d, 0xfe, 0x8f, 0xb3, 0xb7, 0x59, 0x99, 0xff, 0xb8, 0xa5, 0x74, 0xcd, 0xb9, 0x25, 0xcf, 0xbc, + 0xca, 0x2a, 0x05, 0xd2, 0xf5, 0x53, 0x05, 0xd2, 0x57, 0xa1, 0x13, 0xe0, 0xa1, 0x7f, 0x88, 0x03, + 0xa6, 0xb5, 0x34, 0x9c, 0xad, 0x19, 0x6d, 0x0e, 0xa4, 0xfa, 0x3a, 0xff, 0x05, 0xd5, 0xff, 0x2e, + 0xc3, 0x52, 0xcc, 0xed, 0x53, 0x49, 0x72, 0xf6, 0xbd, 0x87, 0xcf, 0x59, 0x74, 0x1f, 0xa9, 0x45, + 0xf7, 0xdd, 0x13, 0x33, 0x9e, 0xc2, 0x92, 0xfb, 0x62, 0xd8, 0xff, 0x29, 0x2c, 0xf0, 0x02, 0x77, + 0xce, 0x55, 0x16, 0x29, 0x3c, 0xac, 0x40, 0x8d, 0x78, 0x66, 0x51, 0x9d, 0x64, 0x1f, 0x8c, 0xef, + 0xe9, 0x5b, 0xd2, 0xdc, 0x5b, 0x76, 0xa4, 0x4b, 0xd2, 0xfa, 0x6f, 0x54, 0x00, 0x76, 0x8f, 0xbd, + 0xe1, 0x6d, 0x66, 0xee, 0x37, 0xa0, 0x3a, 0xeb, 0x4e, 0x1d, 0xe9, 0x4d, 0xb5, 0x94, 0xf6, 0x2c, + 0xa0, 0x01, 0x52, 0x69, 0xa5, 0x92, 0x2d, 0xad, 0x4c, 0x2b, 0x8a, 0x4c, 0x77, 0xe6, 0xdf, 0x85, + 0x2a, 0x75, 0xca, 0xec, 0xca, 0x59, 0xa1, 0xf3, 0x65, 0x3a, 0x00, 0xad, 0x81, 0xd8, 0xdc, 0xb7, + 0x3d, 0xb6, 0x7b, 0x53, 0xc7, 0x5e, 0x31, 0xb2, 0x60, 0xf4, 0x02, 0x74, 0x59, 0x49, 0x2d, 0xee, + 0xc8, 0xb2, 0xc3, 0x0c, 0x34, 0x1f, 0x1b, 0x34, 0x15, 0xb1, 0x01, 0xc1, 0x6b, 0x05, 0xfe, 0x78, + 0x9c, 0x9a, 0x8e, 0xd5, 0x54, 0xb2, 0x60, 0xfd, 0xb3, 0x32, 0x5c, 0x20, 0xfc, 0x7d, 0x3a, 0xf1, + 0x7d, 0x11, 0xe5, 0x49, 0xed, 0x0c, 0x15, 0x79, 0x67, 0xb8, 0x05, 0x0b, 0xac, 0x70, 0x23, 0x22, + 0xd5, 0xcb, 0xd3, 0xb4, 0x81, 0xe9, 0x8e, 0x21, 0xba, 0xcf, 0x9b, 0xfd, 0x4b, 0xa7, 0xef, 0xf5, + 0xf9, 0x4e, 0xdf, 0x17, 0xb2, 0xe5, 0xdd, 0x94, 0x5a, 0x35, 0xe4, 0xfd, 0xec, 0x11, 0x74, 0x8c, + 0xb4, 0x69, 0x20, 0x04, 0xd5, 0xd4, 0x2d, 0x5b, 0xfa, 0x9b, 0x26, 0xec, 0xe6, 0xd8, 0x1c, 0xda, + 0xd1, 0x31, 0x65, 0x67, 0xcd, 0x88, 0xbf, 0xd5, 0x76, 0xa8, 0xff, 0x57, 0x09, 0xce, 0x8b, 0xe3, + 0x59, 0x6e, 0xe5, 0x67, 0x97, 0xe8, 0x06, 0xac, 0x72, 0x93, 0xce, 0xd8, 0x36, 0x0b, 0xcb, 0x97, + 0x19, 0x4c, 0x5e, 0xc6, 0x06, 0xac, 0x46, 0x54, 0xbb, 0xb2, 0x63, 0x98, 0xbc, 0x97, 0x59, 0xa3, + 0x3c, 0xa6, 0xc8, 0xf1, 0xf8, 0x33, 0xec, 0xda, 0x18, 0x67, 0x2d, 0x37, 0x52, 0xf0, 0x26, 0x2e, + 0x5f, 0xa5, 0x7e, 0x04, 0x17, 0xd9, 0x3d, 0xf7, 0x3d, 0x99, 0xa2, 0xb9, 0x4e, 0x47, 0x94, 0xeb, + 0xce, 0xf8, 0xb4, 0x3f, 0x2a, 0xc1, 0xa5, 0x29, 0x98, 0xe7, 0xc9, 0x0b, 0xef, 0x2b, 0xb1, 0x4f, + 0xc9, 0xe2, 0x25, 0xbc, 0xec, 0xea, 0x83, 0x4c, 0xe4, 0x67, 0x55, 0x58, 0xca, 0x75, 0x3a, 0xb5, + 0xce, 0xbd, 0x0c, 0x88, 0x08, 0x21, 0x7e, 0xd3, 0x49, 0x0b, 0x23, 0x7c, 0x87, 0xd5, 0xbc, 0x89, + 0x1b, 0xbf, 0xe7, 0xdc, 0xf1, 0x2d, 0x8c, 0x6c, 0xd6, 0x9b, 0x9d, 0x8d, 0xc4, 0x92, 0xab, 0x4e, + 0x7f, 0xba, 0x93, 0x23, 0x70, 0x7d, 0x67, 0xe2, 0xb2, 0x63, 0x14, 0x2e, 0x65, 0xb6, 0x6b, 0x12, + 0x54, 0x12, 0x18, 0xed, 0xc3, 0x12, 0xbd, 0x54, 0x38, 0x89, 0x46, 0x3e, 0x49, 0xcd, 0x28, 0x5d, + 0x6c, 0x6f, 0xfe, 0x7e, 0x61, 0x4c, 0xef, 0xf3, 0xd1, 0x84, 0x78, 0x9e, 0x9d, 0x79, 0x32, 0x54, + 0xe0, 0xb1, 0xbd, 0xa1, 0xef, 0xc6, 0x78, 0xea, 0xa7, 0xc4, 0xb3, 0xcd, 0x47, 0xcb, 0x78, 0xd2, + 0xd0, 0xfe, 0x26, 0xac, 0x2a, 0x97, 0x3e, 0x6b, 0xa3, 0xaf, 0xa5, 0x73, 0xb8, 0x3b, 0xb0, 0xa2, + 0x5a, 0xd5, 0x19, 0xe6, 0xc8, 0x51, 0x7c, 0x9a, 0x39, 0xf4, 0x3f, 0x2b, 0x43, 0x67, 0x0b, 0x3b, + 0x38, 0xc2, 0x9f, 0xef, 0xe9, 0x75, 0xee, 0x28, 0xbe, 0x92, 0x3f, 0x8a, 0xcf, 0xdd, 0x2b, 0xa8, + 0x2a, 0xee, 0x15, 0x5c, 0x8a, 0xaf, 0x53, 0x90, 0x59, 0x6a, 0x72, 0x0c, 0x61, 0xa1, 0xd7, 0xa1, + 0x3d, 0x0e, 0x6c, 0xd7, 0x0c, 0x8e, 0x07, 0x8f, 0xf1, 0x71, 0xc8, 0x37, 0x8d, 0x9e, 0x72, 0xdb, + 0xd9, 0xde, 0x0a, 0x8d, 0x16, 0xef, 0xfd, 0x2e, 0x3e, 0xa6, 0x57, 0x35, 0xe2, 0x84, 0x90, 0xdd, + 0xe7, 0xab, 0x1a, 0x29, 0xc8, 0xb5, 0x97, 0xa0, 0x19, 0x5f, 0x81, 0x42, 0x0d, 0xa8, 0xde, 0x9d, + 0x38, 0x8e, 0x76, 0x0e, 0x35, 0xa1, 0x46, 0x53, 0x46, 0xad, 0x44, 0x7e, 0xd2, 0xd8, 0x4f, 0x2b, + 0x5f, 0xfb, 0x7f, 0xd0, 0x8c, 0xaf, 0x62, 0xa0, 0x16, 0x2c, 0x3c, 0xf2, 0xde, 0xf5, 0xfc, 0x23, + 0x4f, 0x3b, 0x87, 0x16, 0xa0, 0x72, 0xdb, 0x71, 0xb4, 0x12, 0xea, 0x40, 0x73, 0x37, 0x0a, 0xb0, + 0x49, 0xc4, 0xa7, 0x95, 0x51, 0x17, 0xe0, 0x1d, 0x3b, 0x8c, 0xfc, 0xc0, 0x1e, 0x9a, 0x8e, 0x56, + 0xb9, 0xf6, 0x29, 0x74, 0xe5, 0xca, 0x3c, 0x6a, 0x43, 0x63, 0xc7, 0x8f, 0xde, 0xfe, 0xc4, 0x0e, + 0x23, 0xed, 0x1c, 0xe9, 0xbf, 0xe3, 0x47, 0x0f, 0x02, 0x1c, 0x62, 0x2f, 0xd2, 0x4a, 0x08, 0xa0, + 0xfe, 0xbe, 0xb7, 0x65, 0x87, 0x8f, 0xb5, 0x32, 0x5a, 0xe6, 0x87, 0x6e, 0xa6, 0xb3, 0xcd, 0xcb, + 0xdd, 0x5a, 0x85, 0x0c, 0x8f, 0xbf, 0xaa, 0x48, 0x83, 0x76, 0xdc, 0xe5, 0xde, 0x83, 0x47, 0x5a, + 0x8d, 0x51, 0x4f, 0x7e, 0xd6, 0xaf, 0x59, 0xa0, 0x65, 0x0f, 0x8b, 0xc9, 0x9c, 0x6c, 0x11, 0x31, + 0x48, 0x3b, 0x47, 0x56, 0xc6, 0x4f, 0xeb, 0xb5, 0x12, 0x5a, 0x84, 0x56, 0xea, 0xec, 0x5b, 0x2b, + 0x13, 0xc0, 0xbd, 0x60, 0x3c, 0xe4, 0xba, 0xc5, 0x48, 0x20, 0x8a, 0xba, 0x45, 0x38, 0x51, 0xbd, + 0x76, 0x07, 0x1a, 0x22, 0xd3, 0x21, 0x5d, 0x39, 0x8b, 0xc8, 0xa7, 0x76, 0x0e, 0x2d, 0x41, 0x47, + 0x7a, 0x2f, 0xa8, 0x95, 0x10, 0x82, 0xae, 0xfc, 0xa2, 0x57, 0x2b, 0x5f, 0xdb, 0x00, 0x48, 0x92, + 0x01, 0x42, 0xce, 0xb6, 0x77, 0x68, 0x3a, 0xb6, 0xc5, 0x68, 0x23, 0x4d, 0x84, 0xbb, 0x94, 0x3b, + 0xcc, 0x66, 0xb5, 0xf2, 0xb5, 0x37, 0xa1, 0x21, 0x62, 0x57, 0x02, 0x37, 0xb0, 0xeb, 0x1f, 0x62, + 0x26, 0x99, 0x5d, 0x1c, 0x31, 0x39, 0xde, 0x76, 0xb1, 0x67, 0x69, 0x65, 0x42, 0xc6, 0xa3, 0xb1, + 0x65, 0x46, 0xe2, 0x6e, 0xac, 0x56, 0xd9, 0xf8, 0x8f, 0x65, 0x00, 0x76, 0xfa, 0xeb, 0xfb, 0x81, + 0x85, 0x1c, 0x7a, 0x0b, 0x64, 0xd3, 0x77, 0xc7, 0xbe, 0x27, 0x8e, 0xa6, 0x42, 0xb4, 0x9e, 0x29, + 0xb6, 0xb0, 0x8f, 0x7c, 0x47, 0xce, 0x9b, 0xfe, 0x73, 0xca, 0xfe, 0x99, 0xce, 0xfa, 0x39, 0xe4, + 0x52, 0x6c, 0x24, 0xdf, 0x78, 0x68, 0x0f, 0x1f, 0xc7, 0x47, 0xc6, 0xd3, 0x5f, 0xda, 0x66, 0xba, + 0x0a, 0x7c, 0x57, 0x95, 0xf8, 0x76, 0xa3, 0xc0, 0xf6, 0x46, 0x62, 0x77, 0xd4, 0xcf, 0xa1, 0x27, + 0x99, 0x77, 0xbe, 0x02, 0xe1, 0x46, 0x91, 0xa7, 0xbd, 0x67, 0x43, 0xe9, 0xc0, 0x62, 0xe6, 0x0f, + 0x15, 0xd0, 0x35, 0xf5, 0x83, 0x29, 0xd5, 0x9f, 0x3f, 0xf4, 0x5f, 0x2a, 0xd4, 0x37, 0xc6, 0x66, + 0x43, 0x57, 0xfe, 0x27, 0x00, 0xf4, 0xad, 0x69, 0x13, 0xe4, 0x9e, 0x6c, 0xf6, 0xaf, 0x15, 0xe9, + 0x1a, 0xa3, 0xfa, 0x90, 0xa9, 0xef, 0x2c, 0x54, 0xca, 0x57, 0xb2, 0xfd, 0x93, 0x02, 0x13, 0xfd, + 0x1c, 0xfa, 0x98, 0xc4, 0x10, 0x99, 0x87, 0xa5, 0xe8, 0x65, 0xf5, 0xbe, 0xa7, 0x7e, 0x7f, 0x3a, + 0x0b, 0xc3, 0x87, 0x59, 0xe3, 0x9b, 0x4e, 0x7d, 0xee, 0xc5, 0x7a, 0x71, 0xea, 0x53, 0xd3, 0x9f, + 0x44, 0xfd, 0xa9, 0x31, 0x38, 0x2c, 0x9d, 0x52, 0x3c, 0x69, 0xcb, 0xaa, 0x72, 0x92, 0xcd, 0x4c, + 0x7f, 0xff, 0x36, 0x0b, 0xdb, 0x84, 0x1a, 0x69, 0xf6, 0xda, 0xc3, 0x2b, 0x53, 0x0e, 0x54, 0xd4, + 0x6f, 0x69, 0xfb, 0xeb, 0x45, 0xbb, 0xa7, 0x75, 0x59, 0x7e, 0xae, 0xa9, 0x16, 0x91, 0xf2, 0x89, + 0xa9, 0x5a, 0x97, 0xd5, 0xaf, 0x3f, 0xf5, 0x73, 0xe8, 0xa1, 0xe4, 0xea, 0xd1, 0x0b, 0xd3, 0x54, + 0x41, 0xbe, 0x07, 0x35, 0x8b, 0x6f, 0xbf, 0x0c, 0x88, 0x59, 0xaa, 0xb7, 0x6f, 0x8f, 0x26, 0x81, + 0xc9, 0xd4, 0x78, 0x9a, 0x73, 0xcb, 0x77, 0x15, 0x68, 0xbe, 0x7d, 0x8a, 0x11, 0xf1, 0x92, 0x06, + 0x00, 0xf7, 0x70, 0xf4, 0x1e, 0x7d, 0xb7, 0x17, 0x66, 0x57, 0x94, 0xf8, 0x6f, 0xde, 0x41, 0xa0, + 0x7a, 0x71, 0x66, 0xbf, 0x18, 0xc1, 0x1e, 0xb4, 0xee, 0x91, 0xfc, 0x8a, 0xc6, 0x8c, 0x21, 0x9a, + 0x3a, 0x52, 0xf4, 0x10, 0x28, 0xd6, 0x66, 0x77, 0x4c, 0x3b, 0xcf, 0xcc, 0xd3, 0x55, 0x34, 0x55, + 0xb0, 0xf9, 0x07, 0xb5, 0x6a, 0xe7, 0x39, 0xe5, 0x2d, 0x2c, 0x5b, 0x11, 0x3d, 0xd4, 0x7b, 0x07, + 0x9b, 0x4e, 0x74, 0x30, 0x65, 0x45, 0xa9, 0x1e, 0x27, 0xaf, 0x48, 0xea, 0x18, 0xe3, 0xc0, 0xb0, + 0xcc, 0xac, 0x50, 0x4e, 0x4c, 0xaf, 0xab, 0xa7, 0xc8, 0xf7, 0x2c, 0xa8, 0x7a, 0x26, 0x2c, 0x6d, + 0x05, 0xfe, 0x58, 0x46, 0xf2, 0x8a, 0x12, 0x49, 0xae, 0x5f, 0x41, 0x14, 0x3f, 0x84, 0xb6, 0xc8, + 0xff, 0x69, 0xc6, 0xa2, 0xe6, 0x42, 0xba, 0x4b, 0xc1, 0x89, 0x3f, 0x82, 0xc5, 0x4c, 0x61, 0x41, + 0x2d, 0x74, 0x75, 0xf5, 0x61, 0xd6, 0xec, 0x47, 0x80, 0xe8, 0x7b, 0x64, 0xf9, 0x2f, 0x15, 0xd4, + 0xf1, 0x4d, 0xbe, 0xa3, 0x40, 0x72, 0xbd, 0x70, 0xff, 0x58, 0xf2, 0xbf, 0x02, 0xab, 0xca, 0xe4, + 0x3d, 0xeb, 0x10, 0xf8, 0xc5, 0xe7, 0x13, 0x2a, 0x0c, 0x59, 0x87, 0x70, 0xe2, 0x08, 0x81, 0x7f, + 0xe3, 0xdf, 0x10, 0x34, 0x69, 0x9c, 0x47, 0xa5, 0xf5, 0x7f, 0x61, 0xde, 0xd3, 0x0d, 0xf3, 0x3e, + 0x82, 0xc5, 0xcc, 0x3b, 0x59, 0xb5, 0xd2, 0xaa, 0x1f, 0xd3, 0x16, 0x88, 0x56, 0xe4, 0x27, 0xa6, + 0xea, 0xad, 0x50, 0xf9, 0x0c, 0x75, 0xd6, 0xdc, 0x1f, 0xb0, 0x37, 0xe8, 0xf1, 0xb9, 0xf0, 0x8b, + 0x53, 0x4f, 0x28, 0xe4, 0x0b, 0xcc, 0x5f, 0x7e, 0x14, 0xf4, 0xf5, 0x8e, 0x40, 0x3f, 0x82, 0xc5, + 0xcc, 0x13, 0x21, 0xb5, 0xc6, 0xa8, 0xdf, 0x11, 0xcd, 0x9a, 0xfd, 0x0b, 0x0c, 0x9e, 0x2c, 0x58, + 0x56, 0xbc, 0xc8, 0x40, 0xeb, 0xd3, 0x02, 0x51, 0xf5, 0xd3, 0x8d, 0xd9, 0x0b, 0xea, 0x48, 0x66, + 0x9a, 0xdd, 0x6f, 0x12, 0x22, 0xb3, 0xff, 0xc5, 0xd4, 0x7f, 0xb9, 0xd8, 0x1f, 0x37, 0xc5, 0x0b, + 0xda, 0x85, 0x3a, 0x7b, 0x38, 0x84, 0x9e, 0x55, 0x1f, 0xc2, 0xa4, 0x1e, 0x15, 0xf5, 0x67, 0x3d, + 0x3d, 0x0a, 0x27, 0x4e, 0x44, 0xe8, 0xff, 0x11, 0x74, 0x19, 0x28, 0x66, 0xd0, 0x53, 0x9c, 0x7c, + 0x17, 0x6a, 0xd4, 0xb5, 0x23, 0xe5, 0x81, 0x42, 0xfa, 0x79, 0x50, 0x7f, 0xf6, 0x8b, 0xa0, 0x84, + 0xe2, 0x16, 0x1d, 0xc9, 0xaa, 0x3a, 0x4f, 0x73, 0xea, 0x1b, 0x25, 0xf4, 0x23, 0xe8, 0xb0, 0xc9, + 0x05, 0x37, 0x9e, 0x26, 0xe5, 0x43, 0x58, 0x4e, 0x51, 0xfe, 0x79, 0xa0, 0xb8, 0x51, 0xfa, 0x5f, + 0x1e, 0xdd, 0x7f, 0x42, 0x9f, 0xe7, 0x64, 0x2f, 0xa0, 0xa1, 0xf5, 0xd3, 0xdd, 0xa2, 0xeb, 0x5f, + 0x2f, 0xdc, 0x3f, 0xc6, 0xfc, 0x13, 0xd0, 0xb2, 0x47, 0x85, 0xe8, 0xa5, 0x69, 0xbe, 0x44, 0x85, + 0x73, 0x86, 0x23, 0xf9, 0x01, 0xd4, 0x59, 0x8d, 0x58, 0x6d, 0x80, 0x52, 0xfd, 0x78, 0xc6, 0x5c, + 0x77, 0xbe, 0xf3, 0xe1, 0xc6, 0xc8, 0x8e, 0x0e, 0x26, 0x7b, 0xa4, 0xe5, 0x3a, 0xeb, 0xfa, 0x8a, + 0xed, 0xf3, 0x5f, 0xd7, 0x85, 0x2c, 0xaf, 0xd3, 0xd1, 0xd7, 0x29, 0x82, 0xf1, 0xde, 0x5e, 0x9d, + 0x7e, 0xde, 0xfc, 0x9f, 0x00, 0x00, 0x00, 0xff, 0xff, 0x08, 0xd0, 0x87, 0x99, 0x85, 0x54, 0x00, + 0x00, } // Reference imports to suppress errors if they are not otherwise used. diff --git a/internal/querycoordv2/task/executor.go b/internal/querycoordv2/task/executor.go index 461b0ad4d5867..8694c4380259b 100644 --- a/internal/querycoordv2/task/executor.go +++ b/internal/querycoordv2/task/executor.go @@ -381,14 +381,14 @@ func (ex *Executor) releaseSegment(task *SegmentTask, step int) { func (ex *Executor) executeDmChannelAction(task *ChannelTask, step int) { switch task.Actions()[step].Type() { case ActionTypeGrow: - ex.subDmChannel(task, step) + ex.subscribeChannel(task, step) case ActionTypeReduce: - ex.unsubDmChannel(task, step) + ex.unsubscribeChannel(task, step) } } -func (ex *Executor) subDmChannel(task *ChannelTask, step int) error { +func (ex *Executor) subscribeChannel(task *ChannelTask, step int) error { defer ex.removeTask(task, step) startTs := time.Now() action := task.Actions()[step].(*ChannelAction) @@ -478,7 +478,7 @@ func (ex *Executor) subDmChannel(task *ChannelTask, step int) error { return nil } -func (ex *Executor) unsubDmChannel(task *ChannelTask, step int) error { +func (ex *Executor) unsubscribeChannel(task *ChannelTask, step int) error { defer ex.removeTask(task, step) startTs := time.Now() action := task.Actions()[step].(*ChannelAction) diff --git a/internal/querynodev2/delegator/delegator_data.go b/internal/querynodev2/delegator/delegator_data.go index 57f97631553a9..71d9d9b25a520 100644 --- a/internal/querynodev2/delegator/delegator_data.go +++ b/internal/querynodev2/delegator/delegator_data.go @@ -28,6 +28,7 @@ import ( "github.com/milvus-io/milvus-proto/go-api/v2/commonpb" "github.com/milvus-io/milvus-proto/go-api/v2/msgpb" + "github.com/milvus-io/milvus/internal/proto/datapb" "github.com/milvus-io/milvus/internal/proto/querypb" "github.com/milvus-io/milvus/internal/proto/segcorepb" "github.com/milvus-io/milvus/internal/querynodev2/cluster" @@ -85,8 +86,18 @@ func (sd *shardDelegator) ProcessInsert(insertRecords map[int64]*InsertData) { growing := sd.segmentManager.GetGrowing(segmentID) if growing == nil { var err error - growing, err = segments.NewSegment(sd.collection, segmentID, insertData.PartitionID, sd.collectionID, sd.vchannelName, - segments.SegmentTypeGrowing, 0, insertData.StartPosition, insertData.StartPosition) + growing, err = segments.NewSegment( + sd.collection, + segmentID, + insertData.PartitionID, + sd.collectionID, + sd.vchannelName, + segments.SegmentTypeGrowing, + 0, + insertData.StartPosition, + insertData.StartPosition, + datapb.SegmentLevel_Legacy, + ) if err != nil { log.Error("failed to create new segment", zap.Int64("segmentID", segmentID), @@ -311,6 +322,23 @@ func (sd *shardDelegator) LoadGrowing(ctx context.Context, infos []*querypb.Segm return err } + deletedPks, deletedTss := sd.segmentManager.GetL0DeleteRecords() + for _, segment := range loaded { + err = segment.Delete(deletedPks, deletedTss) + if err != nil { + log.Warn("failed to forward L0 deletions to growing segment", + zap.Int64("segmentID", segment.ID()), + zap.Error(err), + ) + + // clear loaded growing segments + for _, segment := range loaded { + segment.Release() + } + return err + } + } + segmentIDs = lo.Map(loaded, func(segment segments.Segment, _ int) int64 { return segment.ID() }) log.Info("load growing segments done", zap.Int64s("segmentIDs", segmentIDs)) @@ -331,6 +359,10 @@ func (sd *shardDelegator) LoadGrowing(ctx context.Context, infos []*querypb.Segm // LoadSegments load segments local or remotely depends on the target node. func (sd *shardDelegator) LoadSegments(ctx context.Context, req *querypb.LoadSegmentsRequest) error { + if len(req.GetInfos()) == 0 { + return nil + } + log := sd.getLogger(ctx) targetNodeID := req.GetDstNodeID() @@ -396,8 +428,9 @@ func (sd *shardDelegator) LoadSegments(ctx context.Context, req *querypb.LoadSeg } log.Debug("work loads segments done") - // load index need no stream delete and distribution change - if req.GetLoadScope() == querypb.LoadScope_Index { + // load index and L0 segment need no stream delete and distribution change + if req.GetLoadScope() == querypb.LoadScope_Index || + req.GetInfos()[0].GetLevel() == datapb.SegmentLevel_L0 { return nil } @@ -433,11 +466,16 @@ func (sd *shardDelegator) loadStreamDelete(ctx context.Context, return candidate.ID(), candidate }) + level0DeletePks, level0DeleteTss := sd.segmentManager.GetL0DeleteRecords() + sd.deleteMut.Lock() defer sd.deleteMut.Unlock() // apply buffered delete for new segments // no goroutines here since qnv2 has no load merging logic for _, info := range infos { + log := log.With( + zap.Int64("segmentID", info.GetSegmentID()), + ) candidate := idCandidates[info.GetSegmentID()] position := info.GetDeltaPosition() if position == nil { // for compatibility of rolling upgrade from 2.2.x to 2.3 @@ -450,16 +488,42 @@ func (sd *shardDelegator) loadStreamDelete(ctx context.Context, } deleteData := &storage.DeleteData{} + for i, pk := range level0DeletePks { + if candidate.MayPkExist(pk) { + deleteData.Append(pk, level0DeleteTss[i]) + } + } + + if deleteData.RowCount > 0 { + log.Info("forward L0 delete to worker...", + zap.Int64("deleteRowNum", deleteData.RowCount), + ) + err := worker.Delete(ctx, &querypb.DeleteRequest{ + Base: commonpbutil.NewMsgBase(commonpbutil.WithTargetID(targetNodeID)), + CollectionId: info.GetCollectionID(), + PartitionId: info.GetPartitionID(), + SegmentId: info.GetSegmentID(), + PrimaryKeys: storage.ParsePrimaryKeys2IDs(deleteData.Pks), + Timestamps: deleteData.Tss, + }) + if err != nil { + log.Warn("failed to apply delete when LoadSegment", zap.Error(err)) + return err + } + } + + deleteData = &storage.DeleteData{} // start position is dml position for segment // if this position is before deleteBuffer's safe ts, it means some delete shall be read from msgstream if position.GetTimestamp() < sd.deleteBuffer.SafeTs() { log.Info("load delete from stream...") - var err error - deleteData, err = sd.readDeleteFromMsgstream(ctx, position, sd.deleteBuffer.SafeTs(), candidate) + streamDeleteData, err := sd.readDeleteFromMsgstream(ctx, position, sd.deleteBuffer.SafeTs(), candidate) if err != nil { log.Warn("failed to read delete data from msgstream", zap.Error(err)) return err } + + deleteData.Merge(streamDeleteData) log.Info("load delete from stream done") } @@ -472,9 +536,7 @@ func (sd *shardDelegator) loadStreamDelete(ctx context.Context, } for i, pk := range record.DeleteData.Pks { if candidate.MayPkExist(pk) { - deleteData.Pks = append(deleteData.Pks, pk) - deleteData.Tss = append(deleteData.Tss, record.DeleteData.Tss[i]) - deleteData.RowCount++ + deleteData.Append(pk, record.DeleteData.Tss[i]) } } } diff --git a/internal/querynodev2/delegator/delegator_data_test.go b/internal/querynodev2/delegator/delegator_data_test.go index 2d93cac83bbfe..7d6eff94b4cb8 100644 --- a/internal/querynodev2/delegator/delegator_data_test.go +++ b/internal/querynodev2/delegator/delegator_data_test.go @@ -29,6 +29,7 @@ import ( "github.com/milvus-io/milvus-proto/go-api/v2/commonpb" "github.com/milvus-io/milvus-proto/go-api/v2/msgpb" "github.com/milvus-io/milvus-proto/go-api/v2/schemapb" + "github.com/milvus-io/milvus/internal/proto/datapb" "github.com/milvus-io/milvus/internal/proto/querypb" "github.com/milvus-io/milvus/internal/proto/segcorepb" "github.com/milvus-io/milvus/internal/querynodev2/cluster" @@ -232,6 +233,7 @@ func (s *DelegatorDataSuite) TestProcessDelete() { ms.EXPECT().Partition().Return(info.GetPartitionID()) ms.EXPECT().Indexes().Return(nil) ms.EXPECT().RowNum().Return(info.GetNumOfRows()) + ms.EXPECT().Delete(mock.Anything, mock.Anything).Return(nil) ms.EXPECT().MayPkExist(mock.Anything).Call.Return(func(pk storage.PrimaryKey) bool { return pk.EQ(storage.NewInt64PrimaryKey(10)) }) @@ -447,7 +449,25 @@ func (s *DelegatorDataSuite) TestLoadSegments() { ctx, cancel := context.WithCancel(context.Background()) defer cancel() + err := s.delegator.LoadSegments(ctx, &querypb.LoadSegmentsRequest{ + Base: commonpbutil.NewMsgBase(), + DstNodeID: 1, + CollectionID: s.collectionID, + Infos: []*querypb.SegmentLoadInfo{ + { + SegmentID: 200, + PartitionID: 500, + StartPosition: &msgpb.MsgPosition{Timestamp: 20000}, + DeltaPosition: &msgpb.MsgPosition{Timestamp: 20000}, + Deltalogs: []*datapb.FieldBinlog{}, + Level: datapb.SegmentLevel_L0, + }, + }, + }) + s.NoError(err) + + err = s.delegator.LoadSegments(ctx, &querypb.LoadSegmentsRequest{ Base: commonpbutil.NewMsgBase(), DstNodeID: 1, CollectionID: s.collectionID, @@ -676,6 +696,7 @@ func (s *DelegatorDataSuite) TestReleaseSegment() { ms.EXPECT().Collection().Return(info.GetCollectionID()) ms.EXPECT().Indexes().Return(nil) ms.EXPECT().RowNum().Return(info.GetNumOfRows()) + ms.EXPECT().Delete(mock.Anything, mock.Anything).Return(nil) ms.EXPECT().MayPkExist(mock.Anything).Call.Return(func(pk storage.PrimaryKey) bool { return pk.EQ(storage.NewInt64PrimaryKey(10)) }) diff --git a/internal/querynodev2/delegator/delegator_test.go b/internal/querynodev2/delegator/delegator_test.go index bedc51e44dd72..4e130558fca79 100644 --- a/internal/querynodev2/delegator/delegator_test.go +++ b/internal/querynodev2/delegator/delegator_test.go @@ -94,6 +94,7 @@ func (s *DelegatorSuite) SetupTest() { ms.EXPECT().Collection().Return(info.GetCollectionID()) ms.EXPECT().Indexes().Return(nil) ms.EXPECT().RowNum().Return(info.GetNumOfRows()) + ms.EXPECT().Delete(mock.Anything, mock.Anything).Return(nil) return ms }) }, nil) diff --git a/internal/querynodev2/handlers.go b/internal/querynodev2/handlers.go index 21401d5a8d684..4dfb27946a82d 100644 --- a/internal/querynodev2/handlers.go +++ b/internal/querynodev2/handlers.go @@ -27,6 +27,7 @@ import ( "go.uber.org/zap" "github.com/milvus-io/milvus-proto/go-api/v2/commonpb" + "github.com/milvus-io/milvus/internal/proto/datapb" "github.com/milvus-io/milvus/internal/proto/internalpb" "github.com/milvus-io/milvus/internal/proto/planpb" "github.com/milvus-io/milvus/internal/proto/querypb" @@ -43,6 +44,45 @@ import ( "github.com/milvus-io/milvus/pkg/util/timerecord" ) +func loadL0Segments(ctx context.Context, delegator delegator.ShardDelegator, req *querypb.WatchDmChannelsRequest) error { + l0Segments := make([]*querypb.SegmentLoadInfo, 0) + for _, channel := range req.GetInfos() { + for _, segmentID := range channel.GetFlushedSegmentIds() { + segmentInfo, ok := req.GetSegmentInfos()[segmentID] + if !ok || + segmentInfo.GetLevel() != datapb.SegmentLevel_L0 { + continue + } + + l0Segments = append(l0Segments, &querypb.SegmentLoadInfo{ + SegmentID: segmentID, + PartitionID: segmentInfo.PartitionID, + CollectionID: segmentInfo.CollectionID, + BinlogPaths: segmentInfo.Binlogs, + NumOfRows: segmentInfo.NumOfRows, + Statslogs: segmentInfo.Statslogs, + Deltalogs: segmentInfo.Deltalogs, + InsertChannel: segmentInfo.InsertChannel, + StartPosition: segmentInfo.GetStartPosition(), + Level: segmentInfo.GetLevel(), + }) + } + } + + return delegator.LoadSegments(ctx, &querypb.LoadSegmentsRequest{ + Base: req.GetBase(), + DstNodeID: req.GetNodeID(), + Infos: l0Segments, + Schema: req.GetSchema(), + CollectionID: req.GetCollectionID(), + LoadMeta: req.GetLoadMeta(), + ReplicaID: req.GetReplicaID(), + Version: req.GetVersion(), + NeedTransfer: false, + IndexInfoList: req.GetIndexInfoList(), + }) +} + func loadGrowingSegments(ctx context.Context, delegator delegator.ShardDelegator, req *querypb.WatchDmChannelsRequest) error { // load growing segments growingSegments := make([]*querypb.SegmentLoadInfo, 0, len(req.Infos)) diff --git a/internal/querynodev2/segments/manager.go b/internal/querynodev2/segments/manager.go index ce251198b6f6e..853b43a467366 100644 --- a/internal/querynodev2/segments/manager.go +++ b/internal/querynodev2/segments/manager.go @@ -31,7 +31,9 @@ import ( "go.uber.org/zap" + "github.com/milvus-io/milvus/internal/proto/datapb" "github.com/milvus-io/milvus/internal/proto/querypb" + "github.com/milvus-io/milvus/internal/storage" "github.com/milvus-io/milvus/pkg/eventlog" "github.com/milvus-io/milvus/pkg/log" "github.com/milvus-io/milvus/pkg/metrics" @@ -116,6 +118,7 @@ type SegmentManager interface { // and increases the ref count of the corresponding collection, // dup segments will not increase the ref count Put(segmentType SegmentType, segments ...Segment) + UpdateBy(action SegmentAction, filters ...SegmentFilter) int Get(segmentID UniqueID) Segment GetWithType(segmentID UniqueID, typ SegmentType) Segment GetBy(filters ...SegmentFilter) []Segment @@ -124,10 +127,9 @@ type SegmentManager interface { GetAndPin(segments []int64, filters ...SegmentFilter) ([]Segment, error) Unpin(segments []Segment) - UpdateSegmentBy(action SegmentAction, filters ...SegmentFilter) int - GetSealed(segmentID UniqueID) Segment GetGrowing(segmentID UniqueID) Segment + GetL0DeleteRecords() ([]storage.PrimaryKey, []uint64) Empty() bool // Remove removes the given segment, @@ -217,7 +219,7 @@ func (mgr *segmentManager) Put(segmentType SegmentType, segments ...Segment) { } } -func (mgr *segmentManager) UpdateSegmentBy(action SegmentAction, filters ...SegmentFilter) int { +func (mgr *segmentManager) UpdateBy(action SegmentAction, filters ...SegmentFilter) int { mgr.mu.RLock() defer mgr.mu.RUnlock() @@ -407,6 +409,25 @@ func (mgr *segmentManager) GetGrowing(segmentID UniqueID) Segment { return nil } +func (mgr *segmentManager) GetL0DeleteRecords() ([]storage.PrimaryKey, []uint64) { + mgr.mu.RLock() + defer mgr.mu.RUnlock() + + pks := make([]storage.PrimaryKey, 0) + tss := make([]uint64, 0) + for _, segment := range mgr.sealedSegments { + if segment.Level() != datapb.SegmentLevel_L0 { + continue + } + + deletePks, deleteTss := segment.(*L0Segment).DeleteRecords() + pks = append(pks, deletePks...) + tss = append(tss, deleteTss...) + } + + return pks, tss +} + func (mgr *segmentManager) Empty() bool { mgr.mu.RLock() defer mgr.mu.RUnlock() diff --git a/internal/querynodev2/segments/manager_test.go b/internal/querynodev2/segments/manager_test.go index 5a8a374355213..b5a0180a5a2b5 100644 --- a/internal/querynodev2/segments/manager_test.go +++ b/internal/querynodev2/segments/manager_test.go @@ -7,6 +7,7 @@ import ( "github.com/milvus-io/milvus-proto/go-api/v2/commonpb" "github.com/milvus-io/milvus-proto/go-api/v2/schemapb" + "github.com/milvus-io/milvus/internal/proto/datapb" "github.com/milvus-io/milvus/internal/proto/querypb" "github.com/milvus-io/milvus/pkg/util/paramtable" ) @@ -20,7 +21,7 @@ type ManagerSuite struct { partitionIDs []int64 channels []string types []SegmentType - segments []*LocalSegment + segments []Segment mgr *segmentManager } @@ -49,6 +50,7 @@ func (s *ManagerSuite) SetupTest() { 0, nil, nil, + datapb.SegmentLevel_Legacy, ) s.Require().NoError(err) s.segments = append(s.segments, segment) @@ -115,8 +117,8 @@ func (s *ManagerSuite) TestRemoveBy() { func (s *ManagerSuite) TestUpdateBy() { action := IncreaseVersion(1) - s.Equal(2, s.mgr.UpdateSegmentBy(action, WithType(SegmentTypeSealed))) - s.Equal(1, s.mgr.UpdateSegmentBy(action, WithType(SegmentTypeGrowing))) + s.Equal(2, s.mgr.UpdateBy(action, WithType(SegmentTypeSealed))) + s.Equal(1, s.mgr.UpdateBy(action, WithType(SegmentTypeGrowing))) segments := s.mgr.GetBy() for _, segment := range segments { diff --git a/internal/querynodev2/segments/mock_data.go b/internal/querynodev2/segments/mock_data.go index 57d4d8f3630f3..6718a73548c4f 100644 --- a/internal/querynodev2/segments/mock_data.go +++ b/internal/querynodev2/segments/mock_data.go @@ -851,7 +851,7 @@ func SaveDeltaLog(collectionID int64, binlogWriter := storage.NewDeleteBinlogWriter(schemapb.DataType_String, collectionID, partitionID, segmentID) eventWriter, _ := binlogWriter.NextDeleteEventWriter() dData := &storage.DeleteData{ - Pks: []storage.PrimaryKey{&storage.Int64PrimaryKey{Value: 1}, &storage.Int64PrimaryKey{Value: 2}}, + Pks: []storage.PrimaryKey{storage.NewInt64PrimaryKey(1), storage.NewInt64PrimaryKey(2)}, Tss: []typeutil.Timestamp{100, 200}, RowCount: 2, } diff --git a/internal/querynodev2/segments/mock_loader.go b/internal/querynodev2/segments/mock_loader.go index d1f57d8b8a3b5..74d46d0ce3923 100644 --- a/internal/querynodev2/segments/mock_loader.go +++ b/internal/querynodev2/segments/mock_loader.go @@ -173,11 +173,11 @@ func (_c *MockLoader_LoadBloomFilterSet_Call) RunAndReturn(run func(context.Cont } // LoadDeltaLogs provides a mock function with given fields: ctx, segment, deltaLogs -func (_m *MockLoader) LoadDeltaLogs(ctx context.Context, segment *LocalSegment, deltaLogs []*datapb.FieldBinlog) error { +func (_m *MockLoader) LoadDeltaLogs(ctx context.Context, segment Segment, deltaLogs []*datapb.FieldBinlog) error { ret := _m.Called(ctx, segment, deltaLogs) var r0 error - if rf, ok := ret.Get(0).(func(context.Context, *LocalSegment, []*datapb.FieldBinlog) error); ok { + if rf, ok := ret.Get(0).(func(context.Context, Segment, []*datapb.FieldBinlog) error); ok { r0 = rf(ctx, segment, deltaLogs) } else { r0 = ret.Error(0) @@ -193,15 +193,15 @@ type MockLoader_LoadDeltaLogs_Call struct { // LoadDeltaLogs is a helper method to define mock.On call // - ctx context.Context -// - segment *LocalSegment +// - segment Segment // - deltaLogs []*datapb.FieldBinlog func (_e *MockLoader_Expecter) LoadDeltaLogs(ctx interface{}, segment interface{}, deltaLogs interface{}) *MockLoader_LoadDeltaLogs_Call { return &MockLoader_LoadDeltaLogs_Call{Call: _e.mock.On("LoadDeltaLogs", ctx, segment, deltaLogs)} } -func (_c *MockLoader_LoadDeltaLogs_Call) Run(run func(ctx context.Context, segment *LocalSegment, deltaLogs []*datapb.FieldBinlog)) *MockLoader_LoadDeltaLogs_Call { +func (_c *MockLoader_LoadDeltaLogs_Call) Run(run func(ctx context.Context, segment Segment, deltaLogs []*datapb.FieldBinlog)) *MockLoader_LoadDeltaLogs_Call { _c.Call.Run(func(args mock.Arguments) { - run(args[0].(context.Context), args[1].(*LocalSegment), args[2].([]*datapb.FieldBinlog)) + run(args[0].(context.Context), args[1].(Segment), args[2].([]*datapb.FieldBinlog)) }) return _c } @@ -211,7 +211,7 @@ func (_c *MockLoader_LoadDeltaLogs_Call) Return(_a0 error) *MockLoader_LoadDelta return _c } -func (_c *MockLoader_LoadDeltaLogs_Call) RunAndReturn(run func(context.Context, *LocalSegment, []*datapb.FieldBinlog) error) *MockLoader_LoadDeltaLogs_Call { +func (_c *MockLoader_LoadDeltaLogs_Call) RunAndReturn(run func(context.Context, Segment, []*datapb.FieldBinlog) error) *MockLoader_LoadDeltaLogs_Call { _c.Call.Return(run) return _c } diff --git a/internal/querynodev2/segments/mock_segment.go b/internal/querynodev2/segments/mock_segment.go index e5377c7147963..1588bb32d1311 100644 --- a/internal/querynodev2/segments/mock_segment.go +++ b/internal/querynodev2/segments/mock_segment.go @@ -7,6 +7,8 @@ import ( commonpb "github.com/milvus-io/milvus-proto/go-api/v2/commonpb" + datapb "github.com/milvus-io/milvus/internal/proto/datapb" + mock "github.com/stretchr/testify/mock" msgpb "github.com/milvus-io/milvus-proto/go-api/v2/msgpb" @@ -29,40 +31,6 @@ func (_m *MockSegment) EXPECT() *MockSegment_Expecter { return &MockSegment_Expecter{mock: &_m.Mock} } -// AddIndex provides a mock function with given fields: fieldID, index -func (_m *MockSegment) AddIndex(fieldID int64, index *IndexedFieldInfo) { - _m.Called(fieldID, index) -} - -// MockSegment_AddIndex_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'AddIndex' -type MockSegment_AddIndex_Call struct { - *mock.Call -} - -// AddIndex is a helper method to define mock.On call -// - fieldID int64 -// - index *IndexedFieldInfo -func (_e *MockSegment_Expecter) AddIndex(fieldID interface{}, index interface{}) *MockSegment_AddIndex_Call { - return &MockSegment_AddIndex_Call{Call: _e.mock.On("AddIndex", fieldID, index)} -} - -func (_c *MockSegment_AddIndex_Call) Run(run func(fieldID int64, index *IndexedFieldInfo)) *MockSegment_AddIndex_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(int64), args[1].(*IndexedFieldInfo)) - }) - return _c -} - -func (_c *MockSegment_AddIndex_Call) Return() *MockSegment_AddIndex_Call { - _c.Call.Return() - return _c -} - -func (_c *MockSegment_AddIndex_Call) RunAndReturn(run func(int64, *IndexedFieldInfo)) *MockSegment_AddIndex_Call { - _c.Call.Return(run) - return _c -} - // CASVersion provides a mock function with given fields: _a0, _a1 func (_m *MockSegment) CASVersion(_a0 int64, _a1 int64) bool { ret := _m.Called(_a0, _a1) @@ -276,6 +244,48 @@ func (_c *MockSegment_GetIndex_Call) RunAndReturn(run func(int64) *IndexedFieldI return _c } +// HasRawData provides a mock function with given fields: fieldID +func (_m *MockSegment) HasRawData(fieldID int64) bool { + ret := _m.Called(fieldID) + + var r0 bool + if rf, ok := ret.Get(0).(func(int64) bool); ok { + r0 = rf(fieldID) + } else { + r0 = ret.Get(0).(bool) + } + + return r0 +} + +// MockSegment_HasRawData_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'HasRawData' +type MockSegment_HasRawData_Call struct { + *mock.Call +} + +// HasRawData is a helper method to define mock.On call +// - fieldID int64 +func (_e *MockSegment_Expecter) HasRawData(fieldID interface{}) *MockSegment_HasRawData_Call { + return &MockSegment_HasRawData_Call{Call: _e.mock.On("HasRawData", fieldID)} +} + +func (_c *MockSegment_HasRawData_Call) Run(run func(fieldID int64)) *MockSegment_HasRawData_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(int64)) + }) + return _c +} + +func (_c *MockSegment_HasRawData_Call) Return(_a0 bool) *MockSegment_HasRawData_Call { + _c.Call.Return(_a0) + return _c +} + +func (_c *MockSegment_HasRawData_Call) RunAndReturn(run func(int64) bool) *MockSegment_HasRawData_Call { + _c.Call.Return(run) + return _c +} + // ID provides a mock function with given fields: func (_m *MockSegment) ID() int64 { ret := _m.Called() @@ -486,6 +496,89 @@ func (_c *MockSegment_LastDeltaTimestamp_Call) RunAndReturn(run func() uint64) * return _c } +// Level provides a mock function with given fields: +func (_m *MockSegment) Level() datapb.SegmentLevel { + ret := _m.Called() + + var r0 datapb.SegmentLevel + if rf, ok := ret.Get(0).(func() datapb.SegmentLevel); ok { + r0 = rf() + } else { + r0 = ret.Get(0).(datapb.SegmentLevel) + } + + return r0 +} + +// MockSegment_Level_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Level' +type MockSegment_Level_Call struct { + *mock.Call +} + +// Level is a helper method to define mock.On call +func (_e *MockSegment_Expecter) Level() *MockSegment_Level_Call { + return &MockSegment_Level_Call{Call: _e.mock.On("Level")} +} + +func (_c *MockSegment_Level_Call) Run(run func()) *MockSegment_Level_Call { + _c.Call.Run(func(args mock.Arguments) { + run() + }) + return _c +} + +func (_c *MockSegment_Level_Call) Return(_a0 datapb.SegmentLevel) *MockSegment_Level_Call { + _c.Call.Return(_a0) + return _c +} + +func (_c *MockSegment_Level_Call) RunAndReturn(run func() datapb.SegmentLevel) *MockSegment_Level_Call { + _c.Call.Return(run) + return _c +} + +// LoadDeltaData provides a mock function with given fields: deltaData +func (_m *MockSegment) LoadDeltaData(deltaData *storage.DeleteData) error { + ret := _m.Called(deltaData) + + var r0 error + if rf, ok := ret.Get(0).(func(*storage.DeleteData) error); ok { + r0 = rf(deltaData) + } else { + r0 = ret.Error(0) + } + + return r0 +} + +// MockSegment_LoadDeltaData_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'LoadDeltaData' +type MockSegment_LoadDeltaData_Call struct { + *mock.Call +} + +// LoadDeltaData is a helper method to define mock.On call +// - deltaData *storage.DeleteData +func (_e *MockSegment_Expecter) LoadDeltaData(deltaData interface{}) *MockSegment_LoadDeltaData_Call { + return &MockSegment_LoadDeltaData_Call{Call: _e.mock.On("LoadDeltaData", deltaData)} +} + +func (_c *MockSegment_LoadDeltaData_Call) Run(run func(deltaData *storage.DeleteData)) *MockSegment_LoadDeltaData_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(*storage.DeleteData)) + }) + return _c +} + +func (_c *MockSegment_LoadDeltaData_Call) Return(_a0 error) *MockSegment_LoadDeltaData_Call { + _c.Call.Return(_a0) + return _c +} + +func (_c *MockSegment_LoadDeltaData_Call) RunAndReturn(run func(*storage.DeleteData) error) *MockSegment_LoadDeltaData_Call { + _c.Call.Return(run) + return _c +} + // MayPkExist provides a mock function with given fields: pk func (_m *MockSegment) MayPkExist(pk storage.PrimaryKey) bool { ret := _m.Called(pk) diff --git a/internal/querynodev2/segments/mock_segment_manager.go b/internal/querynodev2/segments/mock_segment_manager.go index 7c2413712f0d1..1d86c3a5d50e5 100644 --- a/internal/querynodev2/segments/mock_segment_manager.go +++ b/internal/querynodev2/segments/mock_segment_manager.go @@ -7,6 +7,8 @@ import ( mock "github.com/stretchr/testify/mock" querypb "github.com/milvus-io/milvus/internal/proto/querypb" + + storage "github.com/milvus-io/milvus/internal/storage" ) // MockSegmentManager is an autogenerated mock type for the SegmentManager type @@ -376,6 +378,61 @@ func (_c *MockSegmentManager_GetGrowing_Call) RunAndReturn(run func(int64) Segme return _c } +// GetL0DeleteRecords provides a mock function with given fields: +func (_m *MockSegmentManager) GetL0DeleteRecords() ([]storage.PrimaryKey, []uint64) { + ret := _m.Called() + + var r0 []storage.PrimaryKey + var r1 []uint64 + if rf, ok := ret.Get(0).(func() ([]storage.PrimaryKey, []uint64)); ok { + return rf() + } + if rf, ok := ret.Get(0).(func() []storage.PrimaryKey); ok { + r0 = rf() + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).([]storage.PrimaryKey) + } + } + + if rf, ok := ret.Get(1).(func() []uint64); ok { + r1 = rf() + } else { + if ret.Get(1) != nil { + r1 = ret.Get(1).([]uint64) + } + } + + return r0, r1 +} + +// MockSegmentManager_GetL0DeleteRecords_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'GetL0DeleteRecords' +type MockSegmentManager_GetL0DeleteRecords_Call struct { + *mock.Call +} + +// GetL0DeleteRecords is a helper method to define mock.On call +func (_e *MockSegmentManager_Expecter) GetL0DeleteRecords() *MockSegmentManager_GetL0DeleteRecords_Call { + return &MockSegmentManager_GetL0DeleteRecords_Call{Call: _e.mock.On("GetL0DeleteRecords")} +} + +func (_c *MockSegmentManager_GetL0DeleteRecords_Call) Run(run func()) *MockSegmentManager_GetL0DeleteRecords_Call { + _c.Call.Run(func(args mock.Arguments) { + run() + }) + return _c +} + +func (_c *MockSegmentManager_GetL0DeleteRecords_Call) Return(_a0 []storage.PrimaryKey, _a1 []uint64) *MockSegmentManager_GetL0DeleteRecords_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *MockSegmentManager_GetL0DeleteRecords_Call) RunAndReturn(run func() ([]storage.PrimaryKey, []uint64)) *MockSegmentManager_GetL0DeleteRecords_Call { + _c.Call.Return(run) + return _c +} + // GetSealed provides a mock function with given fields: segmentID func (_m *MockSegmentManager) GetSealed(segmentID int64) Segment { ret := _m.Called(segmentID) @@ -664,8 +721,8 @@ func (_c *MockSegmentManager_Unpin_Call) RunAndReturn(run func([]Segment)) *Mock return _c } -// UpdateSegmentBy provides a mock function with given fields: action, filters -func (_m *MockSegmentManager) UpdateSegmentBy(action SegmentAction, filters ...SegmentFilter) int { +// UpdateBy provides a mock function with given fields: action, filters +func (_m *MockSegmentManager) UpdateBy(action SegmentAction, filters ...SegmentFilter) int { _va := make([]interface{}, len(filters)) for _i := range filters { _va[_i] = filters[_i] @@ -685,20 +742,20 @@ func (_m *MockSegmentManager) UpdateSegmentBy(action SegmentAction, filters ...S return r0 } -// MockSegmentManager_UpdateSegmentBy_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'UpdateSegmentBy' -type MockSegmentManager_UpdateSegmentBy_Call struct { +// MockSegmentManager_UpdateBy_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'UpdateBy' +type MockSegmentManager_UpdateBy_Call struct { *mock.Call } -// UpdateSegmentBy is a helper method to define mock.On call +// UpdateBy is a helper method to define mock.On call // - action SegmentAction // - filters ...SegmentFilter -func (_e *MockSegmentManager_Expecter) UpdateSegmentBy(action interface{}, filters ...interface{}) *MockSegmentManager_UpdateSegmentBy_Call { - return &MockSegmentManager_UpdateSegmentBy_Call{Call: _e.mock.On("UpdateSegmentBy", +func (_e *MockSegmentManager_Expecter) UpdateBy(action interface{}, filters ...interface{}) *MockSegmentManager_UpdateBy_Call { + return &MockSegmentManager_UpdateBy_Call{Call: _e.mock.On("UpdateBy", append([]interface{}{action}, filters...)...)} } -func (_c *MockSegmentManager_UpdateSegmentBy_Call) Run(run func(action SegmentAction, filters ...SegmentFilter)) *MockSegmentManager_UpdateSegmentBy_Call { +func (_c *MockSegmentManager_UpdateBy_Call) Run(run func(action SegmentAction, filters ...SegmentFilter)) *MockSegmentManager_UpdateBy_Call { _c.Call.Run(func(args mock.Arguments) { variadicArgs := make([]SegmentFilter, len(args)-1) for i, a := range args[1:] { @@ -711,12 +768,12 @@ func (_c *MockSegmentManager_UpdateSegmentBy_Call) Run(run func(action SegmentAc return _c } -func (_c *MockSegmentManager_UpdateSegmentBy_Call) Return(_a0 int) *MockSegmentManager_UpdateSegmentBy_Call { +func (_c *MockSegmentManager_UpdateBy_Call) Return(_a0 int) *MockSegmentManager_UpdateBy_Call { _c.Call.Return(_a0) return _c } -func (_c *MockSegmentManager_UpdateSegmentBy_Call) RunAndReturn(run func(SegmentAction, ...SegmentFilter) int) *MockSegmentManager_UpdateSegmentBy_Call { +func (_c *MockSegmentManager_UpdateBy_Call) RunAndReturn(run func(SegmentAction, ...SegmentFilter) int) *MockSegmentManager_UpdateBy_Call { _c.Call.Return(run) return _c } diff --git a/internal/querynodev2/segments/reduce_test.go b/internal/querynodev2/segments/reduce_test.go index 35a653e25390a..e0ecae846d63c 100644 --- a/internal/querynodev2/segments/reduce_test.go +++ b/internal/querynodev2/segments/reduce_test.go @@ -27,6 +27,7 @@ import ( "github.com/milvus-io/milvus-proto/go-api/v2/commonpb" "github.com/milvus-io/milvus-proto/go-api/v2/schemapb" + "github.com/milvus-io/milvus/internal/proto/datapb" "github.com/milvus-io/milvus/internal/proto/planpb" "github.com/milvus-io/milvus/internal/proto/querypb" storage "github.com/milvus-io/milvus/internal/storage" @@ -45,7 +46,7 @@ type ReduceSuite struct { partitionID int64 segmentID int64 collection *Collection - segment *LocalSegment + segment Segment } func (suite *ReduceSuite) SetupSuite() { @@ -80,6 +81,7 @@ func (suite *ReduceSuite) SetupTest() { 0, nil, nil, + datapb.SegmentLevel_Legacy, ) suite.Require().NoError(err) @@ -93,7 +95,7 @@ func (suite *ReduceSuite) SetupTest() { ) suite.Require().NoError(err) for _, binlog := range binlogs { - err = suite.segment.LoadFieldData(binlog.FieldID, int64(msgLength), binlog, false) + err = suite.segment.(*LocalSegment).LoadFieldData(binlog.FieldID, int64(msgLength), binlog, false) suite.Require().NoError(err) } } diff --git a/internal/querynodev2/segments/retrieve_test.go b/internal/querynodev2/segments/retrieve_test.go index d66ad30a198ac..2c48f9ec04d79 100644 --- a/internal/querynodev2/segments/retrieve_test.go +++ b/internal/querynodev2/segments/retrieve_test.go @@ -24,6 +24,7 @@ import ( "github.com/stretchr/testify/suite" "github.com/milvus-io/milvus-proto/go-api/v2/schemapb" + "github.com/milvus-io/milvus/internal/proto/datapb" "github.com/milvus-io/milvus/internal/proto/internalpb" "github.com/milvus-io/milvus/internal/proto/querypb" "github.com/milvus-io/milvus/internal/storage" @@ -46,8 +47,8 @@ type RetrieveSuite struct { partitionID int64 segmentID int64 collection *Collection - sealed *LocalSegment - growing *LocalSegment + sealed Segment + growing Segment } func (suite *RetrieveSuite) SetupSuite() { @@ -91,6 +92,7 @@ func (suite *RetrieveSuite) SetupTest() { 0, nil, nil, + datapb.SegmentLevel_Legacy, ) suite.Require().NoError(err) @@ -104,7 +106,7 @@ func (suite *RetrieveSuite) SetupTest() { ) suite.Require().NoError(err) for _, binlog := range binlogs { - err = suite.sealed.LoadFieldData(binlog.FieldID, int64(msgLength), binlog, false) + err = suite.sealed.(*LocalSegment).LoadFieldData(binlog.FieldID, int64(msgLength), binlog, false) suite.Require().NoError(err) } @@ -117,10 +119,11 @@ func (suite *RetrieveSuite) SetupTest() { 0, nil, nil, + datapb.SegmentLevel_Legacy, ) suite.Require().NoError(err) - insertMsg, err := genInsertMsg(suite.collection, suite.partitionID, suite.growing.segmentID, msgLength) + insertMsg, err := genInsertMsg(suite.collection, suite.partitionID, suite.growing.ID(), msgLength) suite.Require().NoError(err) insertRecord, err := storage.TransferInsertMsgToInsertRecord(suite.collection.Schema(), insertMsg) suite.Require().NoError(err) diff --git a/internal/querynodev2/segments/search_test.go b/internal/querynodev2/segments/search_test.go index d9b8723a18ec0..17116de30aad8 100644 --- a/internal/querynodev2/segments/search_test.go +++ b/internal/querynodev2/segments/search_test.go @@ -23,6 +23,7 @@ import ( "github.com/stretchr/testify/suite" "github.com/milvus-io/milvus-proto/go-api/v2/schemapb" + "github.com/milvus-io/milvus/internal/proto/datapb" "github.com/milvus-io/milvus/internal/proto/querypb" storage "github.com/milvus-io/milvus/internal/storage" "github.com/milvus-io/milvus/internal/util/initcore" @@ -38,8 +39,8 @@ type SearchSuite struct { partitionID int64 segmentID int64 collection *Collection - sealed *LocalSegment - growing *LocalSegment + sealed Segment + growing Segment } func (suite *SearchSuite) SetupSuite() { @@ -82,6 +83,7 @@ func (suite *SearchSuite) SetupTest() { 0, nil, nil, + datapb.SegmentLevel_Legacy, ) suite.Require().NoError(err) @@ -95,7 +97,7 @@ func (suite *SearchSuite) SetupTest() { ) suite.Require().NoError(err) for _, binlog := range binlogs { - err = suite.sealed.LoadFieldData(binlog.FieldID, int64(msgLength), binlog, false) + err = suite.sealed.(*LocalSegment).LoadFieldData(binlog.FieldID, int64(msgLength), binlog, false) suite.Require().NoError(err) } @@ -108,10 +110,11 @@ func (suite *SearchSuite) SetupTest() { 0, nil, nil, + datapb.SegmentLevel_Legacy, ) suite.Require().NoError(err) - insertMsg, err := genInsertMsg(suite.collection, suite.partitionID, suite.growing.segmentID, msgLength) + insertMsg, err := genInsertMsg(suite.collection, suite.partitionID, suite.growing.ID(), msgLength) suite.Require().NoError(err) insertRecord, err := storage.TransferInsertMsgToInsertRecord(suite.collection.Schema(), insertMsg) suite.Require().NoError(err) diff --git a/internal/querynodev2/segments/segment.go b/internal/querynodev2/segments/segment.go index ae6193173dac1..5c743ed329d27 100644 --- a/internal/querynodev2/segments/segment.go +++ b/internal/querynodev2/segments/segment.go @@ -113,6 +113,10 @@ func (s *baseSegment) Type() SegmentType { return s.typ } +func (s *baseSegment) Level() datapb.SegmentLevel { + return datapb.SegmentLevel_Legacy +} + func (s *baseSegment) StartPosition() *msgpb.MsgPosition { return s.startPosition } @@ -162,11 +166,16 @@ func NewSegment(collection *Collection, version int64, startPosition *msgpb.MsgPosition, deltaPosition *msgpb.MsgPosition, -) (*LocalSegment, error) { + level datapb.SegmentLevel, +) (Segment, error) { /* CSegmentInterface NewSegment(CCollection collection, uint64_t segment_id, SegmentType seg_type); */ + if level == datapb.SegmentLevel_L0 { + return NewL0Segment(collection, segmentID, partitionID, collectionID, shard, segmentType, version, startPosition, deltaPosition) + } + var segmentPtr C.CSegmentInterface switch segmentType { case SegmentTypeSealed: diff --git a/internal/querynodev2/segments/segment_interface.go b/internal/querynodev2/segments/segment_interface.go index 71f24cc90da66..aa047ab1e821a 100644 --- a/internal/querynodev2/segments/segment_interface.go +++ b/internal/querynodev2/segments/segment_interface.go @@ -20,6 +20,7 @@ import ( "context" "github.com/milvus-io/milvus-proto/go-api/v2/msgpb" + "github.com/milvus-io/milvus/internal/proto/datapb" "github.com/milvus-io/milvus/internal/proto/segcorepb" storage "github.com/milvus-io/milvus/internal/storage" "github.com/milvus-io/milvus/pkg/util/typeutil" @@ -35,6 +36,7 @@ type Segment interface { CASVersion(int64, int64) bool StartPosition() *msgpb.MsgPosition Type() SegmentType + Level() datapb.SegmentLevel RLock() error RUnlock() @@ -46,15 +48,17 @@ type Segment interface { MemSize() int64 // Index related - AddIndex(fieldID int64, index *IndexedFieldInfo) GetIndex(fieldID int64) *IndexedFieldInfo ExistIndex(fieldID int64) bool Indexes() []*IndexedFieldInfo + HasRawData(fieldID int64) bool // Modification related Insert(rowIDs []int64, timestamps []typeutil.Timestamp, record *segcorepb.InsertRecord) error Delete(primaryKeys []storage.PrimaryKey, timestamps []typeutil.Timestamp) error + LoadDeltaData(deltaData *storage.DeleteData) error LastDeltaTimestamp() uint64 + Release() // Bloom filter related UpdateBloomFilter(pks []storage.PrimaryKey) @@ -63,6 +67,4 @@ type Segment interface { // Read operations Search(ctx context.Context, searchReq *SearchRequest) (*SearchResult, error) Retrieve(ctx context.Context, plan *RetrievePlan) (*segcorepb.RetrieveResults, error) - - Release() } diff --git a/internal/querynodev2/segments/segment_l0.go b/internal/querynodev2/segments/segment_l0.go new file mode 100644 index 0000000000000..285939db7976e --- /dev/null +++ b/internal/querynodev2/segments/segment_l0.go @@ -0,0 +1,164 @@ +// Copyright 2023 yah01 +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package segments + +import ( + "context" + "sync" + + "github.com/samber/lo" + "go.uber.org/zap" + + "github.com/milvus-io/milvus-proto/go-api/v2/msgpb" + "github.com/milvus-io/milvus/internal/proto/datapb" + "github.com/milvus-io/milvus/internal/proto/segcorepb" + storage "github.com/milvus-io/milvus/internal/storage" + "github.com/milvus-io/milvus/pkg/log" + "github.com/milvus-io/milvus/pkg/util/merr" + "github.com/milvus-io/milvus/pkg/util/typeutil" +) + +var _ Segment = (*L0Segment)(nil) + +type L0Segment struct { + baseSegment + + dataGuard sync.RWMutex + pks []storage.PrimaryKey + tss []uint64 +} + +func NewL0Segment(collection *Collection, + segmentID int64, + partitionID int64, + collectionID int64, + shard string, + segmentType SegmentType, + version int64, + startPosition *msgpb.MsgPosition, + deltaPosition *msgpb.MsgPosition, +) (Segment, error) { + /* + CSegmentInterface + NewSegment(CCollection collection, uint64_t segment_id, SegmentType seg_type); + */ + + log.Info("create L0 segment", + zap.Int64("collectionID", collectionID), + zap.Int64("partitionID", partitionID), + zap.Int64("segmentID", segmentID), + zap.String("segmentType", segmentType.String())) + + segment := &L0Segment{ + baseSegment: newBaseSegment(segmentID, partitionID, collectionID, shard, segmentType, version, startPosition), + } + + return segment, nil +} + +func (s *L0Segment) RLock() error { + return nil +} + +func (s *L0Segment) RUnlock() {} + +func (s *L0Segment) InsertCount() int64 { + return 0 +} + +func (s *L0Segment) RowNum() int64 { + return 0 +} + +func (s *L0Segment) MemSize() int64 { + return lo.SumBy(s.pks, func(pk storage.PrimaryKey) int64 { + return pk.Size() + 8 + }) +} + +func (s *L0Segment) LastDeltaTimestamp() uint64 { + s.dataGuard.RLock() + defer s.dataGuard.RUnlock() + + last, err := lo.Last(s.tss) + if err != nil { + return 0 + } + return last +} + +func (s *L0Segment) GetIndex(fieldID int64) *IndexedFieldInfo { + return nil +} + +func (s *L0Segment) ExistIndex(fieldID int64) bool { + return false +} + +func (s *L0Segment) HasRawData(fieldID int64) bool { + return false +} + +func (s *L0Segment) Indexes() []*IndexedFieldInfo { + return nil +} + +func (s *L0Segment) Type() SegmentType { + return s.typ +} + +func (s *L0Segment) Level() datapb.SegmentLevel { + return datapb.SegmentLevel_L0 +} + +func (s *L0Segment) Search(ctx context.Context, searchReq *SearchRequest) (*SearchResult, error) { + return nil, nil +} + +func (s *L0Segment) Retrieve(ctx context.Context, plan *RetrievePlan) (*segcorepb.RetrieveResults, error) { + return nil, nil +} + +func (s *L0Segment) Insert(rowIDs []int64, timestamps []typeutil.Timestamp, record *segcorepb.InsertRecord) error { + return merr.WrapErrIoFailedReason("insert not supported for L0 segment") +} + +func (s *L0Segment) Delete(primaryKeys []storage.PrimaryKey, timestamps []typeutil.Timestamp) error { + return merr.WrapErrIoFailedReason("delete not supported for L0 segment") +} + +func (s *L0Segment) LoadDeltaData(deltaData *storage.DeleteData) error { + s.dataGuard.Lock() + defer s.dataGuard.Unlock() + + s.pks = append(s.pks, deltaData.Pks...) + s.tss = append(s.tss, deltaData.Tss...) + return nil +} + +func (s *L0Segment) DeleteRecords() ([]storage.PrimaryKey, []uint64) { + s.dataGuard.RLock() + defer s.dataGuard.RUnlock() + + return s.pks, s.tss +} + +func (s *L0Segment) Release() { + s.dataGuard.Lock() + defer s.dataGuard.Unlock() + + s.pks = nil + s.tss = nil +} diff --git a/internal/querynodev2/segments/segment_loader.go b/internal/querynodev2/segments/segment_loader.go index 9941d7d9c6f78..c1b883c06b22d 100644 --- a/internal/querynodev2/segments/segment_loader.go +++ b/internal/querynodev2/segments/segment_loader.go @@ -16,17 +16,6 @@ package segments -/* -#cgo pkg-config: milvus_segcore milvus_common - -#include "segcore/collection_c.h" -#include "segcore/segment_c.h" -#include "segcore/segcore_init_c.h" -#include "common/init_c.h" - -*/ -import "C" - import ( "context" "fmt" @@ -64,14 +53,12 @@ const ( UsedDiskMemoryRatio = 4 ) -var ErrReadDeltaMsgFailed = errors.New("ReadDeltaMsgFailed") - type Loader interface { // Load loads binlogs, and spawn segments, // NOTE: make sure the ref count of the corresponding collection will never go down to 0 during this Load(ctx context.Context, collectionID int64, segmentType SegmentType, version int64, segments ...*querypb.SegmentLoadInfo) ([]Segment, error) - LoadDeltaLogs(ctx context.Context, segment *LocalSegment, deltaLogs []*datapb.FieldBinlog) error + LoadDeltaLogs(ctx context.Context, segment Segment, deltaLogs []*datapb.FieldBinlog) error // LoadBloomFilterSet loads needed statslog for RemoteSegment. LoadBloomFilterSet(ctx context.Context, collectionID int64, version int64, infos ...*querypb.SegmentLoadInfo) ([]*pkoracle.BloomFilterSet, error) @@ -201,10 +188,10 @@ func (loader *segmentLoader) Load(ctx context.Context, } defer loader.freeRequest(resource) - newSegments := typeutil.NewConcurrentMap[int64, *LocalSegment]() - loaded := typeutil.NewConcurrentMap[int64, *LocalSegment]() + newSegments := typeutil.NewConcurrentMap[int64, Segment]() + loaded := typeutil.NewConcurrentMap[int64, Segment]() defer func() { - newSegments.Range(func(_ int64, s *LocalSegment) bool { + newSegments.Range(func(_ int64, s Segment) bool { s.Release() return true }) @@ -212,10 +199,10 @@ func (loader *segmentLoader) Load(ctx context.Context, }() for _, info := range infos { - segmentID := info.SegmentID - partitionID := info.PartitionID - collectionID := info.CollectionID - shard := info.InsertChannel + segmentID := info.GetSegmentID() + partitionID := info.GetPartitionID() + collectionID := info.GetCollectionID() + shard := info.GetInsertChannel() collection := loader.manager.Collection.Get(collectionID) if collection == nil { @@ -223,7 +210,19 @@ func (loader *segmentLoader) Load(ctx context.Context, log.Warn("failed to get collection", zap.Error(err)) return nil, err } - segment, err := NewSegment(collection, segmentID, partitionID, collectionID, shard, segmentType, version, info.GetStartPosition(), info.GetDeltaPosition()) + + segment, err := NewSegment( + collection, + segmentID, + partitionID, + collectionID, + shard, + segmentType, + version, + info.GetStartPosition(), + info.GetDeltaPosition(), + info.GetLevel(), + ) if err != nil { log.Warn("load segment failed when create new segment", zap.Int64("partitionID", partitionID), @@ -243,7 +242,13 @@ func (loader *segmentLoader) Load(ctx context.Context, segment, _ := newSegments.Get(segmentID) tr := timerecord.NewTimeRecorder("loadDurationPerSegment") - err := loader.loadSegment(ctx, segment, loadInfo) + + var err error + if loadInfo.GetLevel() == datapb.SegmentLevel_L0 { + err = loader.LoadDeltaLogs(ctx, segment, loadInfo.GetDeltalogs()) + } else { + err = loader.loadSegment(ctx, segment.(*LocalSegment), loadInfo) + } if err != nil { log.Warn("load segment failed when load data into memory", zap.Int64("partitionID", partitionID), @@ -282,7 +287,7 @@ func (loader *segmentLoader) Load(ctx context.Context, log.Info("all segment load done") var result []Segment - loaded.Range(func(_ int64, s *LocalSegment) bool { + loaded.Range(func(_ int64, s Segment) bool { result = append(result, s) return true }) @@ -303,7 +308,7 @@ func (loader *segmentLoader) prepare(segmentType SegmentType, version int64, seg loader.loadingSegments.Insert(segment.GetSegmentID(), newLoadResult()) } else { // try to update segment version before skip load operation - loader.manager.Segment.UpdateSegmentBy(IncreaseVersion(version), + loader.manager.Segment.UpdateBy(IncreaseVersion(version), WithType(segmentType), WithID(segment.SegmentID)) log.Info("skip loaded/loading segment", zap.Int64("segmentID", segment.GetSegmentID()), zap.Bool("isLoaded", len(loader.manager.Segment.GetBy(WithType(segmentType), WithID(segment.GetSegmentID()))) > 0), @@ -342,7 +347,8 @@ func (loader *segmentLoader) requestResource(ctx context.Context, infos ...*quer // we need to deal with empty infos case separately, // because the following judgement for requested resources are based on current status and static config // which may block empty-load operations by accident - if len(infos) == 0 { + if len(infos) == 0 || + infos[0].GetLevel() == datapb.SegmentLevel_L0 { return resource, 0, nil } @@ -789,7 +795,7 @@ func (loader *segmentLoader) loadBloomFilter(ctx context.Context, segmentID int6 return nil } -func (loader *segmentLoader) LoadDeltaLogs(ctx context.Context, segment *LocalSegment, deltaLogs []*datapb.FieldBinlog) error { +func (loader *segmentLoader) LoadDeltaLogs(ctx context.Context, segment Segment, deltaLogs []*datapb.FieldBinlog) error { dCodec := storage.DeleteCodec{} var blobs []*storage.Blob for _, deltaLog := range deltaLogs { @@ -811,7 +817,7 @@ func (loader *segmentLoader) LoadDeltaLogs(ctx context.Context, segment *LocalSe } } if len(blobs) == 0 { - log.Info("there are no delta logs saved with segment, skip loading delete record", zap.Any("segmentID", segment.segmentID)) + log.Info("there are no delta logs saved with segment, skip loading delete record", zap.Any("segmentID", segment.ID())) return nil } _, _, deltaData, err := dCodec.Deserialize(blobs) @@ -1120,8 +1126,3 @@ func getBinlogDataSize(fieldBinlog *datapb.FieldBinlog) int64 { return fieldSize } - -func getIndexEngineVersion() (minimal, current int32) { - cMinimal, cCurrent := C.GetMinimalIndexVersion(), C.GetCurrentIndexVersion() - return int32(cMinimal), int32(cCurrent) -} diff --git a/internal/querynodev2/segments/segment_test.go b/internal/querynodev2/segments/segment_test.go index 87fd9a476de4e..5abe64d3a50c7 100644 --- a/internal/querynodev2/segments/segment_test.go +++ b/internal/querynodev2/segments/segment_test.go @@ -7,6 +7,7 @@ import ( "github.com/stretchr/testify/suite" "github.com/milvus-io/milvus-proto/go-api/v2/schemapb" + "github.com/milvus-io/milvus/internal/proto/datapb" "github.com/milvus-io/milvus/internal/proto/querypb" storage "github.com/milvus-io/milvus/internal/storage" "github.com/milvus-io/milvus/internal/util/initcore" @@ -24,8 +25,8 @@ type SegmentSuite struct { partitionID int64 segmentID int64 collection *Collection - sealed *LocalSegment - growing *LocalSegment + sealed Segment + growing Segment } func (suite *SegmentSuite) SetupSuite() { @@ -69,6 +70,7 @@ func (suite *SegmentSuite) SetupTest() { 0, nil, nil, + datapb.SegmentLevel_Legacy, ) suite.Require().NoError(err) @@ -82,7 +84,7 @@ func (suite *SegmentSuite) SetupTest() { ) suite.Require().NoError(err) for _, binlog := range binlogs { - err = suite.sealed.LoadFieldData(binlog.FieldID, int64(msgLength), binlog, false) + err = suite.sealed.(*LocalSegment).LoadFieldData(binlog.FieldID, int64(msgLength), binlog, false) suite.Require().NoError(err) } @@ -95,10 +97,11 @@ func (suite *SegmentSuite) SetupTest() { 0, nil, nil, + datapb.SegmentLevel_Legacy, ) suite.Require().NoError(err) - insertMsg, err := genInsertMsg(suite.collection, suite.partitionID, suite.growing.segmentID, msgLength) + insertMsg, err := genInsertMsg(suite.collection, suite.partitionID, suite.growing.ID(), msgLength) suite.Require().NoError(err) insertRecord, err := storage.TransferInsertMsgToInsertRecord(suite.collection.Schema(), insertMsg) suite.Require().NoError(err) @@ -159,13 +162,15 @@ func (suite *SegmentSuite) TestCASVersion() { func (suite *SegmentSuite) TestSegmentReleased() { suite.sealed.Release() - suite.sealed.ptrLock.RLock() - suite.False(suite.sealed.isValid()) - suite.sealed.ptrLock.RUnlock() - suite.EqualValues(0, suite.sealed.InsertCount()) - suite.EqualValues(0, suite.sealed.RowNum()) - suite.EqualValues(0, suite.sealed.MemSize()) - suite.False(suite.sealed.HasRawData(101)) + sealed := suite.sealed.(*LocalSegment) + + sealed.ptrLock.RLock() + suite.False(sealed.isValid()) + sealed.ptrLock.RUnlock() + suite.EqualValues(0, sealed.InsertCount()) + suite.EqualValues(0, sealed.RowNum()) + suite.EqualValues(0, sealed.MemSize()) + suite.False(sealed.HasRawData(101)) } func TestSegment(t *testing.T) { diff --git a/internal/querynodev2/segments/utils.go b/internal/querynodev2/segments/utils.go index 33af9c4422da5..1a7b1dc54f853 100644 --- a/internal/querynodev2/segments/utils.go +++ b/internal/querynodev2/segments/utils.go @@ -1,5 +1,16 @@ package segments +/* +#cgo pkg-config: milvus_segcore milvus_common + +#include "segcore/collection_c.h" +#include "segcore/segment_c.h" +#include "segcore/segcore_init_c.h" +#include "common/init_c.h" + +*/ +import "C" + import ( "bytes" "context" @@ -296,3 +307,8 @@ func mergeRequestCost(requestCosts []*internalpb.CostAggregation) *internalpb.Co return result } + +func getIndexEngineVersion() (minimal, current int32) { + cMinimal, cCurrent := C.GetMinimalIndexVersion(), C.GetCurrentIndexVersion() + return int32(cMinimal), int32(cCurrent) +} diff --git a/internal/querynodev2/server_test.go b/internal/querynodev2/server_test.go index 1e59d3274ebea..4b3795074c211 100644 --- a/internal/querynodev2/server_test.go +++ b/internal/querynodev2/server_test.go @@ -31,6 +31,7 @@ import ( "github.com/milvus-io/milvus-proto/go-api/v2/commonpb" "github.com/milvus-io/milvus-proto/go-api/v2/schemapb" + "github.com/milvus-io/milvus/internal/proto/datapb" "github.com/milvus-io/milvus/internal/proto/querypb" "github.com/milvus-io/milvus/internal/querynodev2/optimizers" "github.com/milvus-io/milvus/internal/querynodev2/segments" @@ -220,7 +221,17 @@ func (suite *QueryNodeSuite) TestStop() { schema := segments.GenTestCollectionSchema("test_stop", schemapb.DataType_Int64) collection := segments.NewCollection(1, schema, nil, querypb.LoadType_LoadCollection) - segment, err := segments.NewSegment(collection, 100, 10, 1, "test_stop_channel", segments.SegmentTypeSealed, 1, nil, nil) + segment, err := segments.NewSegment( + collection, + 100, + 10, + 1, + "test_stop_channel", + segments.SegmentTypeSealed, + 1, nil, + nil, + datapb.SegmentLevel_Legacy, + ) suite.NoError(err) suite.node.manager.Segment.Put(segments.SegmentTypeSealed, segment) err = suite.node.Stop() diff --git a/internal/querynodev2/services.go b/internal/querynodev2/services.go index 54ef2f6345512..91a470a6d3db4 100644 --- a/internal/querynodev2/services.go +++ b/internal/querynodev2/services.go @@ -311,6 +311,11 @@ func (node *QueryNode) WatchDmChannels(ctx context.Context, req *querypb.WatchDm pipeline.ExcludedSegments(droppedInfos...) } + err = loadL0Segments(ctx, delegator, req) + if err != nil { + log.Warn("failed to load l0 segments", zap.Error(err)) + return merr.Status(err), nil + } err = loadGrowingSegments(ctx, delegator, req) if err != nil { msg := "failed to load growing segments" diff --git a/internal/querynodev2/services_test.go b/internal/querynodev2/services_test.go index 494f27f3254c7..43f3baccbf594 100644 --- a/internal/querynodev2/services_test.go +++ b/internal/querynodev2/services_test.go @@ -257,6 +257,13 @@ func (suite *ServiceSuite) TestWatchDmChannelsInt64() { ctx := context.Background() // data + deltaLogs, err := segments.SaveDeltaLog(suite.collectionID, + suite.partitionIDs[0], + suite.flushedSegmentIDs[0], + suite.node.cacheChunkManager, + ) + suite.NoError(err) + req := &querypb.WatchDmChannelsRequest{ Base: &commonpb.MsgBase{ MsgType: commonpb.MsgType_WatchDmChannels, @@ -275,6 +282,16 @@ func (suite *ServiceSuite) TestWatchDmChannelsInt64() { DroppedSegmentIds: suite.droppedSegmentIDs, }, }, + SegmentInfos: map[int64]*datapb.SegmentInfo{ + suite.flushedSegmentIDs[0]: { + ID: suite.flushedSegmentIDs[0], + CollectionID: suite.collectionID, + PartitionID: suite.partitionIDs[0], + InsertChannel: suite.vchannel, + Deltalogs: deltaLogs, + Level: datapb.SegmentLevel_L0, + }, + }, Schema: segments.GenTestCollectionSchema(suite.collectionName, schemapb.DataType_Int64), LoadMeta: &querypb.LoadMetaInfo{ LoadType: querypb.LoadType_LoadCollection, diff --git a/internal/storage/data_codec.go b/internal/storage/data_codec.go index f6c558745b5db..b228f0301f187 100644 --- a/internal/storage/data_codec.go +++ b/internal/storage/data_codec.go @@ -848,6 +848,16 @@ func (data *DeleteData) Append(pk PrimaryKey, ts Timestamp) { data.RowCount++ } +func (data *DeleteData) Merge(other *DeleteData) { + data.Pks = append(other.Pks, other.Pks...) + data.Tss = append(other.Tss, other.Tss...) + data.RowCount += other.RowCount + + other.Pks = nil + other.Tss = nil + other.RowCount = 0 +} + // DeleteCodec serializes and deserializes the delete data type DeleteCodec struct{} diff --git a/internal/storage/data_codec_test.go b/internal/storage/data_codec_test.go index d05068255be61..477a6c21c74f1 100644 --- a/internal/storage/data_codec_test.go +++ b/internal/storage/data_codec_test.go @@ -465,6 +465,25 @@ func TestDeleteCodec(t *testing.T) { assert.Equal(t, sid, int64(1)) assert.Equal(t, data, deleteData) }) + + t.Run("merge", func(t *testing.T) { + first := &DeleteData{ + Pks: []PrimaryKey{NewInt64PrimaryKey(1)}, + Tss: []uint64{100}, + RowCount: 1, + } + + second := &DeleteData{ + Pks: []PrimaryKey{NewInt64PrimaryKey(2)}, + Tss: []uint64{100}, + RowCount: 1, + } + + first.Merge(second) + assert.Equal(t, len(first.Pks), 2) + assert.Equal(t, len(first.Tss), 2) + assert.Equal(t, first.RowCount, int64(2)) + }) } func TestUpgradeDeleteLog(t *testing.T) {