Remove collection meta after GC finished (#21595) (#21671)

Signed-off-by: longjiquan <jiquan.long@zilliz.com>
pull/21695/head
Jiquan Long 2023-01-13 15:43:41 +08:00 committed by GitHub
parent 845719c2bb
commit a13c375c48
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
37 changed files with 2055 additions and 808 deletions

View File

@ -299,6 +299,9 @@ mock-datanode:
mock-rootcoord:
mockery --name=RootCoord --dir=$(PWD)/internal/types --output=$(PWD)/internal/mocks --filename=mock_rootcoord.go --with-expecter
mock-datacoord:
mockery --name=DataCoord --dir=$(PWD)/internal/types --output=$(PWD)/internal/mocks --filename=mock_datacoord.go --with-expecter
mock-tnx-kv:
mockery --name=TxnKV --dir=$(PWD)/internal/kv --output=$(PWD)/internal/kv/mocks --filename=TxnKV.go --with-expecter

View File

@ -1221,6 +1221,10 @@ func (m *meta) DropChannelCheckpoint(vChannel string) error {
return nil
}
func (m *meta) GcConfirm(ctx context.Context, collectionID, partitionID UniqueID) bool {
return m.catalog.GcConfirm(ctx, collectionID, partitionID)
}
// addNewSeg update metrics update for a new segment.
func (s *segMetricMutation) addNewSeg(state commonpb.SegmentState, rowCount int64) {
s.stateChange[state.String()]++

View File

@ -25,18 +25,18 @@ import (
"testing"
"github.com/golang/protobuf/proto"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/mock"
"github.com/stretchr/testify/require"
"github.com/milvus-io/milvus-proto/go-api/commonpb"
"github.com/milvus-io/milvus/internal/common"
"github.com/milvus-io/milvus/internal/kv"
"github.com/milvus-io/milvus/internal/metastore/kv/datacoord"
"github.com/milvus-io/milvus/internal/metastore/mocks"
"github.com/milvus-io/milvus/internal/mocks"
"github.com/milvus-io/milvus/internal/proto/datapb"
"github.com/milvus-io/milvus/internal/proto/internalpb"
"github.com/milvus-io/milvus/internal/util"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/mock"
"github.com/stretchr/testify/require"
)
func TestMetaReloadFromKV(t *testing.T) {
@ -964,3 +964,17 @@ func TestChannelCP(t *testing.T) {
assert.NoError(t, err)
})
}
func Test_meta_GcConfirm(t *testing.T) {
m := &meta{}
catalog := mocks.NewDataCoordCatalog(t)
m.catalog = catalog
catalog.On("GcConfirm",
mock.Anything,
mock.AnythingOfType("int64"),
mock.AnythingOfType("int64")).
Return(false)
assert.False(t, m.GcConfirm(context.TODO(), 100, 10000))
}

View File

@ -1475,3 +1475,21 @@ func (s *Server) CheckHealth(ctx context.Context, req *milvuspb.CheckHealthReque
return &milvuspb.CheckHealthResponse{IsHealthy: true, Reasons: errReasons}, nil
}
func (s *Server) GcConfirm(ctx context.Context, request *datapb.GcConfirmRequest) (*datapb.GcConfirmResponse, error) {
resp := &datapb.GcConfirmResponse{
Status: &commonpb.Status{
ErrorCode: commonpb.ErrorCode_UnexpectedError,
},
GcFinished: false,
}
if s.isClosed() {
resp.Status.Reason = msgDataCoordIsUnhealthy(Params.DataCoordCfg.GetNodeID())
return resp, nil
}
resp.GcFinished = s.meta.GcConfirm(ctx, request.GetCollectionId(), request.GetPartitionId())
resp.Status.ErrorCode = commonpb.ErrorCode_Success
return resp, nil
}

View File

@ -4,10 +4,11 @@ import (
"context"
"testing"
"github.com/milvus-io/milvus/internal/proto/datapb"
"github.com/milvus-io/milvus-proto/go-api/commonpb"
"github.com/milvus-io/milvus/internal/mocks"
"github.com/milvus-io/milvus/internal/proto/datapb"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/mock"
)
func TestBroadcastAlteredCollection(t *testing.T) {
@ -54,3 +55,35 @@ func TestBroadcastAlteredCollection(t *testing.T) {
assert.NotNil(t, s.meta.collections[1].Properties)
})
}
func TestServer_GcConfirm(t *testing.T) {
t.Run("closed server", func(t *testing.T) {
s := &Server{}
s.stateCode.Store(commonpb.StateCode_Initializing)
resp, err := s.GcConfirm(context.TODO(), &datapb.GcConfirmRequest{CollectionId: 100, PartitionId: 10000})
assert.NoError(t, err)
assert.NotEqual(t, commonpb.ErrorCode_Success, resp.GetStatus().GetErrorCode())
})
t.Run("normal case", func(t *testing.T) {
s := &Server{}
s.stateCode.Store(commonpb.StateCode_Healthy)
m := &meta{}
catalog := mocks.NewDataCoordCatalog(t)
m.catalog = catalog
catalog.On("GcConfirm",
mock.Anything,
mock.AnythingOfType("int64"),
mock.AnythingOfType("int64")).
Return(false)
s.meta = m
resp, err := s.GcConfirm(context.TODO(), &datapb.GcConfirmRequest{CollectionId: 100, PartitionId: 10000})
assert.NoError(t, err)
assert.Equal(t, commonpb.ErrorCode_Success, resp.GetStatus().GetErrorCode())
assert.False(t, resp.GetGcFinished())
})
}

View File

@ -796,3 +796,16 @@ func (c *Client) CheckHealth(ctx context.Context, req *milvuspb.CheckHealthReque
}
return ret.(*milvuspb.CheckHealthResponse), err
}
func (c *Client) GcConfirm(ctx context.Context, req *datapb.GcConfirmRequest) (*datapb.GcConfirmResponse, error) {
ret, err := c.grpcClient.ReCall(ctx, func(client datapb.DataCoordClient) (any, error) {
if !funcutil.CheckCtxValid(ctx) {
return nil, ctx.Err()
}
return client.GcConfirm(ctx, req)
})
if err != nil || ret == nil {
return nil, err
}
return ret.(*datapb.GcConfirmResponse), err
}

View File

@ -418,3 +418,7 @@ func (s *Server) BroadcastAlteredCollection(ctx context.Context, request *datapb
func (s *Server) CheckHealth(ctx context.Context, req *milvuspb.CheckHealthRequest) (*milvuspb.CheckHealthResponse, error) {
return s.dataCoord.CheckHealth(ctx, req)
}
func (s *Server) GcConfirm(ctx context.Context, request *datapb.GcConfirmRequest) (*datapb.GcConfirmResponse, error) {
return s.dataCoord.GcConfirm(ctx, request)
}

View File

@ -33,6 +33,8 @@ import (
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
type MockDataCoord struct {
types.DataCoord
states *milvuspb.ComponentStates
status *commonpb.Status
err error

View File

@ -620,6 +620,10 @@ func (m *MockDataCoord) CheckHealth(ctx context.Context, req *milvuspb.CheckHeal
return nil, nil
}
func (m *MockDataCoord) GcConfirm(ctx context.Context, req *datapb.GcConfirmRequest) (*datapb.GcConfirmResponse, error) {
return nil, nil
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
type MockProxy struct {
MockBase

View File

@ -82,10 +82,10 @@ type MetaKv_CompareValueAndSwap_Call struct {
}
// CompareValueAndSwap is a helper method to define mock.On call
// - key string
// - value string
// - target string
// - opts ...clientv3.OpOption
// - key string
// - value string
// - target string
// - opts ...clientv3.OpOption
func (_e *MetaKv_Expecter) CompareValueAndSwap(key interface{}, value interface{}, target interface{}, opts ...interface{}) *MetaKv_CompareValueAndSwap_Call {
return &MetaKv_CompareValueAndSwap_Call{Call: _e.mock.On("CompareValueAndSwap",
append([]interface{}{key, value, target}, opts...)...)}
@ -143,10 +143,10 @@ type MetaKv_CompareVersionAndSwap_Call struct {
}
// CompareVersionAndSwap is a helper method to define mock.On call
// - key string
// - version int64
// - target string
// - opts ...clientv3.OpOption
// - key string
// - version int64
// - target string
// - opts ...clientv3.OpOption
func (_e *MetaKv_Expecter) CompareVersionAndSwap(key interface{}, version interface{}, target interface{}, opts ...interface{}) *MetaKv_CompareVersionAndSwap_Call {
return &MetaKv_CompareVersionAndSwap_Call{Call: _e.mock.On("CompareVersionAndSwap",
append([]interface{}{key, version, target}, opts...)...)}
@ -190,7 +190,7 @@ type MetaKv_GetPath_Call struct {
}
// GetPath is a helper method to define mock.On call
// - key string
// - key string
func (_e *MetaKv_Expecter) GetPath(key interface{}) *MetaKv_GetPath_Call {
return &MetaKv_GetPath_Call{Call: _e.mock.On("GetPath", key)}
}
@ -234,7 +234,7 @@ type MetaKv_Grant_Call struct {
}
// Grant is a helper method to define mock.On call
// - ttl int64
// - ttl int64
func (_e *MetaKv_Expecter) Grant(ttl interface{}) *MetaKv_Grant_Call {
return &MetaKv_Grant_Call{Call: _e.mock.On("Grant", ttl)}
}
@ -280,7 +280,7 @@ type MetaKv_KeepAlive_Call struct {
}
// KeepAlive is a helper method to define mock.On call
// - id clientv3.LeaseID
// - id clientv3.LeaseID
func (_e *MetaKv_Expecter) KeepAlive(id interface{}) *MetaKv_KeepAlive_Call {
return &MetaKv_KeepAlive_Call{Call: _e.mock.On("KeepAlive", id)}
}
@ -324,7 +324,7 @@ type MetaKv_Load_Call struct {
}
// Load is a helper method to define mock.On call
// - key string
// - key string
func (_e *MetaKv_Expecter) Load(key interface{}) *MetaKv_Load_Call {
return &MetaKv_Load_Call{Call: _e.mock.On("Load", key)}
}
@ -379,7 +379,7 @@ type MetaKv_LoadWithPrefix_Call struct {
}
// LoadWithPrefix is a helper method to define mock.On call
// - key string
// - key string
func (_e *MetaKv_Expecter) LoadWithPrefix(key interface{}) *MetaKv_LoadWithPrefix_Call {
return &MetaKv_LoadWithPrefix_Call{Call: _e.mock.On("LoadWithPrefix", key)}
}
@ -443,7 +443,7 @@ type MetaKv_LoadWithPrefix2_Call struct {
}
// LoadWithPrefix2 is a helper method to define mock.On call
// - key string
// - key string
func (_e *MetaKv_Expecter) LoadWithPrefix2(key interface{}) *MetaKv_LoadWithPrefix2_Call {
return &MetaKv_LoadWithPrefix2_Call{Call: _e.mock.On("LoadWithPrefix2", key)}
}
@ -505,7 +505,7 @@ type MetaKv_LoadWithRevision_Call struct {
}
// LoadWithRevision is a helper method to define mock.On call
// - key string
// - key string
func (_e *MetaKv_Expecter) LoadWithRevision(key interface{}) *MetaKv_LoadWithRevision_Call {
return &MetaKv_LoadWithRevision_Call{Call: _e.mock.On("LoadWithRevision", key)}
}
@ -576,7 +576,7 @@ type MetaKv_LoadWithRevisionAndVersions_Call struct {
}
// LoadWithRevisionAndVersions is a helper method to define mock.On call
// - key string
// - key string
func (_e *MetaKv_Expecter) LoadWithRevisionAndVersions(key interface{}) *MetaKv_LoadWithRevisionAndVersions_Call {
return &MetaKv_LoadWithRevisionAndVersions_Call{Call: _e.mock.On("LoadWithRevisionAndVersions", key)}
}
@ -622,7 +622,7 @@ type MetaKv_MultiLoad_Call struct {
}
// MultiLoad is a helper method to define mock.On call
// - keys []string
// - keys []string
func (_e *MetaKv_Expecter) MultiLoad(keys interface{}) *MetaKv_MultiLoad_Call {
return &MetaKv_MultiLoad_Call{Call: _e.mock.On("MultiLoad", keys)}
}
@ -659,7 +659,7 @@ type MetaKv_MultiRemove_Call struct {
}
// MultiRemove is a helper method to define mock.On call
// - keys []string
// - keys []string
func (_e *MetaKv_Expecter) MultiRemove(keys interface{}) *MetaKv_MultiRemove_Call {
return &MetaKv_MultiRemove_Call{Call: _e.mock.On("MultiRemove", keys)}
}
@ -696,7 +696,7 @@ type MetaKv_MultiRemoveWithPrefix_Call struct {
}
// MultiRemoveWithPrefix is a helper method to define mock.On call
// - keys []string
// - keys []string
func (_e *MetaKv_Expecter) MultiRemoveWithPrefix(keys interface{}) *MetaKv_MultiRemoveWithPrefix_Call {
return &MetaKv_MultiRemoveWithPrefix_Call{Call: _e.mock.On("MultiRemoveWithPrefix", keys)}
}
@ -733,7 +733,7 @@ type MetaKv_MultiSave_Call struct {
}
// MultiSave is a helper method to define mock.On call
// - kvs map[string]string
// - kvs map[string]string
func (_e *MetaKv_Expecter) MultiSave(kvs interface{}) *MetaKv_MultiSave_Call {
return &MetaKv_MultiSave_Call{Call: _e.mock.On("MultiSave", kvs)}
}
@ -770,8 +770,8 @@ type MetaKv_MultiSaveAndRemove_Call struct {
}
// MultiSaveAndRemove is a helper method to define mock.On call
// - saves map[string]string
// - removals []string
// - saves map[string]string
// - removals []string
func (_e *MetaKv_Expecter) MultiSaveAndRemove(saves interface{}, removals interface{}) *MetaKv_MultiSaveAndRemove_Call {
return &MetaKv_MultiSaveAndRemove_Call{Call: _e.mock.On("MultiSaveAndRemove", saves, removals)}
}
@ -808,8 +808,8 @@ type MetaKv_MultiSaveAndRemoveWithPrefix_Call struct {
}
// MultiSaveAndRemoveWithPrefix is a helper method to define mock.On call
// - saves map[string]string
// - removals []string
// - saves map[string]string
// - removals []string
func (_e *MetaKv_Expecter) MultiSaveAndRemoveWithPrefix(saves interface{}, removals interface{}) *MetaKv_MultiSaveAndRemoveWithPrefix_Call {
return &MetaKv_MultiSaveAndRemoveWithPrefix_Call{Call: _e.mock.On("MultiSaveAndRemoveWithPrefix", saves, removals)}
}
@ -846,7 +846,7 @@ type MetaKv_Remove_Call struct {
}
// Remove is a helper method to define mock.On call
// - key string
// - key string
func (_e *MetaKv_Expecter) Remove(key interface{}) *MetaKv_Remove_Call {
return &MetaKv_Remove_Call{Call: _e.mock.On("Remove", key)}
}
@ -883,7 +883,7 @@ type MetaKv_RemoveWithPrefix_Call struct {
}
// RemoveWithPrefix is a helper method to define mock.On call
// - key string
// - key string
func (_e *MetaKv_Expecter) RemoveWithPrefix(key interface{}) *MetaKv_RemoveWithPrefix_Call {
return &MetaKv_RemoveWithPrefix_Call{Call: _e.mock.On("RemoveWithPrefix", key)}
}
@ -920,8 +920,8 @@ type MetaKv_Save_Call struct {
}
// Save is a helper method to define mock.On call
// - key string
// - value string
// - key string
// - value string
func (_e *MetaKv_Expecter) Save(key interface{}, value interface{}) *MetaKv_Save_Call {
return &MetaKv_Save_Call{Call: _e.mock.On("Save", key, value)}
}
@ -958,8 +958,8 @@ type MetaKv_SaveWithIgnoreLease_Call struct {
}
// SaveWithIgnoreLease is a helper method to define mock.On call
// - key string
// - value string
// - key string
// - value string
func (_e *MetaKv_Expecter) SaveWithIgnoreLease(key interface{}, value interface{}) *MetaKv_SaveWithIgnoreLease_Call {
return &MetaKv_SaveWithIgnoreLease_Call{Call: _e.mock.On("SaveWithIgnoreLease", key, value)}
}
@ -996,9 +996,9 @@ type MetaKv_SaveWithLease_Call struct {
}
// SaveWithLease is a helper method to define mock.On call
// - key string
// - value string
// - id clientv3.LeaseID
// - key string
// - value string
// - id clientv3.LeaseID
func (_e *MetaKv_Expecter) SaveWithLease(key interface{}, value interface{}, id interface{}) *MetaKv_SaveWithLease_Call {
return &MetaKv_SaveWithLease_Call{Call: _e.mock.On("SaveWithLease", key, value, id)}
}
@ -1035,9 +1035,9 @@ type MetaKv_WalkWithPrefix_Call struct {
}
// WalkWithPrefix is a helper method to define mock.On call
// - prefix string
// - paginationSize int
// - fn func([]byte , []byte) error
// - prefix string
// - paginationSize int
// - fn func([]byte , []byte) error
func (_e *MetaKv_Expecter) WalkWithPrefix(prefix interface{}, paginationSize interface{}, fn interface{}) *MetaKv_WalkWithPrefix_Call {
return &MetaKv_WalkWithPrefix_Call{Call: _e.mock.On("WalkWithPrefix", prefix, paginationSize, fn)}
}
@ -1076,7 +1076,7 @@ type MetaKv_Watch_Call struct {
}
// Watch is a helper method to define mock.On call
// - key string
// - key string
func (_e *MetaKv_Expecter) Watch(key interface{}) *MetaKv_Watch_Call {
return &MetaKv_Watch_Call{Call: _e.mock.On("Watch", key)}
}
@ -1115,7 +1115,7 @@ type MetaKv_WatchWithPrefix_Call struct {
}
// WatchWithPrefix is a helper method to define mock.On call
// - key string
// - key string
func (_e *MetaKv_Expecter) WatchWithPrefix(key interface{}) *MetaKv_WatchWithPrefix_Call {
return &MetaKv_WatchWithPrefix_Call{Call: _e.mock.On("WatchWithPrefix", key)}
}
@ -1154,8 +1154,8 @@ type MetaKv_WatchWithRevision_Call struct {
}
// WatchWithRevision is a helper method to define mock.On call
// - key string
// - revision int64
// - key string
// - revision int64
func (_e *MetaKv_Expecter) WatchWithRevision(key interface{}, revision interface{}) *MetaKv_WatchWithRevision_Call {
return &MetaKv_WatchWithRevision_Call{Call: _e.mock.On("WatchWithRevision", key, revision)}
}

View File

@ -44,8 +44,8 @@ type SnapShotKV_Load_Call struct {
}
// Load is a helper method to define mock.On call
// - key string
// - ts uint64
// - key string
// - ts uint64
func (_e *SnapShotKV_Expecter) Load(key interface{}, ts interface{}) *SnapShotKV_Load_Call {
return &SnapShotKV_Load_Call{Call: _e.mock.On("Load", key, ts)}
}
@ -100,8 +100,8 @@ type SnapShotKV_LoadWithPrefix_Call struct {
}
// LoadWithPrefix is a helper method to define mock.On call
// - key string
// - ts uint64
// - key string
// - ts uint64
func (_e *SnapShotKV_Expecter) LoadWithPrefix(key interface{}, ts interface{}) *SnapShotKV_LoadWithPrefix_Call {
return &SnapShotKV_LoadWithPrefix_Call{Call: _e.mock.On("LoadWithPrefix", key, ts)}
}
@ -138,8 +138,8 @@ type SnapShotKV_MultiSave_Call struct {
}
// MultiSave is a helper method to define mock.On call
// - kvs map[string]string
// - ts uint64
// - kvs map[string]string
// - ts uint64
func (_e *SnapShotKV_Expecter) MultiSave(kvs interface{}, ts interface{}) *SnapShotKV_MultiSave_Call {
return &SnapShotKV_MultiSave_Call{Call: _e.mock.On("MultiSave", kvs, ts)}
}
@ -176,9 +176,9 @@ type SnapShotKV_MultiSaveAndRemoveWithPrefix_Call struct {
}
// MultiSaveAndRemoveWithPrefix is a helper method to define mock.On call
// - saves map[string]string
// - removals []string
// - ts uint64
// - saves map[string]string
// - removals []string
// - ts uint64
func (_e *SnapShotKV_Expecter) MultiSaveAndRemoveWithPrefix(saves interface{}, removals interface{}, ts interface{}) *SnapShotKV_MultiSaveAndRemoveWithPrefix_Call {
return &SnapShotKV_MultiSaveAndRemoveWithPrefix_Call{Call: _e.mock.On("MultiSaveAndRemoveWithPrefix", saves, removals, ts)}
}
@ -215,9 +215,9 @@ type SnapShotKV_Save_Call struct {
}
// Save is a helper method to define mock.On call
// - key string
// - value string
// - ts uint64
// - key string
// - value string
// - ts uint64
func (_e *SnapShotKV_Expecter) Save(key interface{}, value interface{}, ts interface{}) *SnapShotKV_Save_Call {
return &SnapShotKV_Save_Call{Call: _e.mock.On("Save", key, value, ts)}
}

View File

@ -71,7 +71,7 @@ type TxnKV_Load_Call struct {
}
// Load is a helper method to define mock.On call
// - key string
// - key string
func (_e *TxnKV_Expecter) Load(key interface{}) *TxnKV_Load_Call {
return &TxnKV_Load_Call{Call: _e.mock.On("Load", key)}
}
@ -126,7 +126,7 @@ type TxnKV_LoadWithPrefix_Call struct {
}
// LoadWithPrefix is a helper method to define mock.On call
// - key string
// - key string
func (_e *TxnKV_Expecter) LoadWithPrefix(key interface{}) *TxnKV_LoadWithPrefix_Call {
return &TxnKV_LoadWithPrefix_Call{Call: _e.mock.On("LoadWithPrefix", key)}
}
@ -172,7 +172,7 @@ type TxnKV_MultiLoad_Call struct {
}
// MultiLoad is a helper method to define mock.On call
// - keys []string
// - keys []string
func (_e *TxnKV_Expecter) MultiLoad(keys interface{}) *TxnKV_MultiLoad_Call {
return &TxnKV_MultiLoad_Call{Call: _e.mock.On("MultiLoad", keys)}
}
@ -209,7 +209,7 @@ type TxnKV_MultiRemove_Call struct {
}
// MultiRemove is a helper method to define mock.On call
// - keys []string
// - keys []string
func (_e *TxnKV_Expecter) MultiRemove(keys interface{}) *TxnKV_MultiRemove_Call {
return &TxnKV_MultiRemove_Call{Call: _e.mock.On("MultiRemove", keys)}
}
@ -246,7 +246,7 @@ type TxnKV_MultiRemoveWithPrefix_Call struct {
}
// MultiRemoveWithPrefix is a helper method to define mock.On call
// - keys []string
// - keys []string
func (_e *TxnKV_Expecter) MultiRemoveWithPrefix(keys interface{}) *TxnKV_MultiRemoveWithPrefix_Call {
return &TxnKV_MultiRemoveWithPrefix_Call{Call: _e.mock.On("MultiRemoveWithPrefix", keys)}
}
@ -283,7 +283,7 @@ type TxnKV_MultiSave_Call struct {
}
// MultiSave is a helper method to define mock.On call
// - kvs map[string]string
// - kvs map[string]string
func (_e *TxnKV_Expecter) MultiSave(kvs interface{}) *TxnKV_MultiSave_Call {
return &TxnKV_MultiSave_Call{Call: _e.mock.On("MultiSave", kvs)}
}
@ -320,8 +320,8 @@ type TxnKV_MultiSaveAndRemove_Call struct {
}
// MultiSaveAndRemove is a helper method to define mock.On call
// - saves map[string]string
// - removals []string
// - saves map[string]string
// - removals []string
func (_e *TxnKV_Expecter) MultiSaveAndRemove(saves interface{}, removals interface{}) *TxnKV_MultiSaveAndRemove_Call {
return &TxnKV_MultiSaveAndRemove_Call{Call: _e.mock.On("MultiSaveAndRemove", saves, removals)}
}
@ -358,8 +358,8 @@ type TxnKV_MultiSaveAndRemoveWithPrefix_Call struct {
}
// MultiSaveAndRemoveWithPrefix is a helper method to define mock.On call
// - saves map[string]string
// - removals []string
// - saves map[string]string
// - removals []string
func (_e *TxnKV_Expecter) MultiSaveAndRemoveWithPrefix(saves interface{}, removals interface{}) *TxnKV_MultiSaveAndRemoveWithPrefix_Call {
return &TxnKV_MultiSaveAndRemoveWithPrefix_Call{Call: _e.mock.On("MultiSaveAndRemoveWithPrefix", saves, removals)}
}
@ -396,7 +396,7 @@ type TxnKV_Remove_Call struct {
}
// Remove is a helper method to define mock.On call
// - key string
// - key string
func (_e *TxnKV_Expecter) Remove(key interface{}) *TxnKV_Remove_Call {
return &TxnKV_Remove_Call{Call: _e.mock.On("Remove", key)}
}
@ -433,7 +433,7 @@ type TxnKV_RemoveWithPrefix_Call struct {
}
// RemoveWithPrefix is a helper method to define mock.On call
// - key string
// - key string
func (_e *TxnKV_Expecter) RemoveWithPrefix(key interface{}) *TxnKV_RemoveWithPrefix_Call {
return &TxnKV_RemoveWithPrefix_Call{Call: _e.mock.On("RemoveWithPrefix", key)}
}
@ -470,8 +470,8 @@ type TxnKV_Save_Call struct {
}
// Save is a helper method to define mock.On call
// - key string
// - value string
// - key string
// - value string
func (_e *TxnKV_Expecter) Save(key interface{}, value interface{}) *TxnKV_Save_Call {
return &TxnKV_Save_Call{Call: _e.mock.On("Save", key, value)}
}

View File

@ -118,6 +118,8 @@ type DataCoordCatalog interface {
ListChannelCheckpoint(ctx context.Context) (map[string]*internalpb.MsgPosition, error)
SaveChannelCheckpoint(ctx context.Context, vChannel string, pos *internalpb.MsgPosition) error
DropChannelCheckpoint(ctx context.Context, vChannel string) error
GcConfirm(ctx context.Context, collectionID, partitionID typeutil.UniqueID) bool
}
type IndexCoordCatalog interface {

View File

@ -23,11 +23,9 @@ import (
"strconv"
"strings"
"github.com/golang/protobuf/proto"
"go.uber.org/zap"
"golang.org/x/exp/maps"
"golang.org/x/sync/errgroup"
"github.com/golang/protobuf/proto"
"github.com/milvus-io/milvus-proto/go-api/commonpb"
"github.com/milvus-io/milvus/internal/kv"
"github.com/milvus-io/milvus/internal/log"
@ -38,6 +36,8 @@ import (
"github.com/milvus-io/milvus/internal/util/etcd"
"github.com/milvus-io/milvus/internal/util/metautil"
"github.com/milvus-io/milvus/internal/util/typeutil"
"go.uber.org/zap"
"golang.org/x/sync/errgroup"
)
var maxEtcdTxnNum = 128
@ -538,6 +538,23 @@ func (kc *Catalog) unmarshalBinlog(binlogType storage.BinlogType, collectionID,
return result, nil
}
const allPartitionID = -1
// GcConfirm returns true if related collection/partition is not found.
// DataCoord will remove all the meta eventually after GC is finished.
func (kc *Catalog) GcConfirm(ctx context.Context, collectionID, partitionID typeutil.UniqueID) bool {
prefix := buildCollectionPrefix(collectionID)
if partitionID != allPartitionID {
prefix = buildPartitionPrefix(collectionID, partitionID)
}
keys, values, err := kc.MetaKv.LoadWithPrefix(prefix)
if err != nil {
// error case can be regarded as not finished.
return false
}
return len(keys) == 0 && len(values) == 0
}
func fillLogPathByLogID(chunkManagerRootPath string, binlogType storage.BinlogType, collectionID, partitionID,
segmentID typeutil.UniqueID, fieldBinlog *datapb.FieldBinlog) error {
for _, binlog := range fieldBinlog.Binlogs {
@ -796,3 +813,11 @@ func buildChannelRemovePath(channel string) string {
func buildChannelCPKey(vChannel string) string {
return fmt.Sprintf("%s/%s", ChannelCheckpointPrefix, vChannel)
}
func buildCollectionPrefix(collectionID typeutil.UniqueID) string {
return fmt.Sprintf("%s/%d", SegmentPrefix, collectionID)
}
func buildPartitionPrefix(collectionID, partitionID typeutil.UniqueID) string {
return fmt.Sprintf("%s/%d/%d", SegmentPrefix, collectionID, partitionID)
}

View File

@ -791,3 +791,20 @@ func verifySavedKvsForDroppedSegment(t *testing.T, savedKvs map[string]string) {
assert.True(t, ok)
verifySegmentInfo2(t, []byte(ret))
}
func TestCatalog_GcConfirm(t *testing.T) {
kc := &Catalog{}
txn := mocks.NewMetaKv(t)
kc.MetaKv = txn
txn.On("LoadWithPrefix",
mock.AnythingOfType("string")).
Return(nil, nil, errors.New("error mock LoadWithPrefix")).
Once()
assert.False(t, kc.GcConfirm(context.TODO(), 100, 10000))
txn.On("LoadWithPrefix",
mock.AnythingOfType("string")).
Return(nil, nil, nil)
assert.True(t, kc.GcConfirm(context.TODO(), 100, 10000))
}

View File

@ -9,8 +9,6 @@ import (
internalpb "github.com/milvus-io/milvus/internal/proto/internalpb"
mock "github.com/stretchr/testify/mock"
model "github.com/milvus-io/milvus/internal/metastore/model"
)
// DataCoordCatalog is an autogenerated mock type for the DataCoordCatalog type
@ -46,8 +44,8 @@ type DataCoordCatalog_AddSegment_Call struct {
}
// AddSegment is a helper method to define mock.On call
// - ctx context.Context
// - segment *datapb.SegmentInfo
// - ctx context.Context
// - segment *datapb.SegmentInfo
func (_e *DataCoordCatalog_Expecter) AddSegment(ctx interface{}, segment interface{}) *DataCoordCatalog_AddSegment_Call {
return &DataCoordCatalog_AddSegment_Call{Call: _e.mock.On("AddSegment", ctx, segment)}
}
@ -64,82 +62,6 @@ func (_c *DataCoordCatalog_AddSegment_Call) Return(_a0 error) *DataCoordCatalog_
return _c
}
// AlterIndex provides a mock function with given fields: ctx, newIndex
func (_m *DataCoordCatalog) AlterIndex(ctx context.Context, newIndex *model.Index) error {
ret := _m.Called(ctx, newIndex)
var r0 error
if rf, ok := ret.Get(0).(func(context.Context, *model.Index) error); ok {
r0 = rf(ctx, newIndex)
} else {
r0 = ret.Error(0)
}
return r0
}
// DataCoordCatalog_AlterIndex_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'AlterIndex'
type DataCoordCatalog_AlterIndex_Call struct {
*mock.Call
}
// AlterIndex is a helper method to define mock.On call
// - ctx context.Context
// - newIndex *model.Index
func (_e *DataCoordCatalog_Expecter) AlterIndex(ctx interface{}, newIndex interface{}) *DataCoordCatalog_AlterIndex_Call {
return &DataCoordCatalog_AlterIndex_Call{Call: _e.mock.On("AlterIndex", ctx, newIndex)}
}
func (_c *DataCoordCatalog_AlterIndex_Call) Run(run func(ctx context.Context, newIndex *model.Index)) *DataCoordCatalog_AlterIndex_Call {
_c.Call.Run(func(args mock.Arguments) {
run(args[0].(context.Context), args[1].(*model.Index))
})
return _c
}
func (_c *DataCoordCatalog_AlterIndex_Call) Return(_a0 error) *DataCoordCatalog_AlterIndex_Call {
_c.Call.Return(_a0)
return _c
}
// AlterIndexes provides a mock function with given fields: ctx, newIndexes
func (_m *DataCoordCatalog) AlterIndexes(ctx context.Context, newIndexes []*model.Index) error {
ret := _m.Called(ctx, newIndexes)
var r0 error
if rf, ok := ret.Get(0).(func(context.Context, []*model.Index) error); ok {
r0 = rf(ctx, newIndexes)
} else {
r0 = ret.Error(0)
}
return r0
}
// DataCoordCatalog_AlterIndexes_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'AlterIndexes'
type DataCoordCatalog_AlterIndexes_Call struct {
*mock.Call
}
// AlterIndexes is a helper method to define mock.On call
// - ctx context.Context
// - newIndexes []*model.Index
func (_e *DataCoordCatalog_Expecter) AlterIndexes(ctx interface{}, newIndexes interface{}) *DataCoordCatalog_AlterIndexes_Call {
return &DataCoordCatalog_AlterIndexes_Call{Call: _e.mock.On("AlterIndexes", ctx, newIndexes)}
}
func (_c *DataCoordCatalog_AlterIndexes_Call) Run(run func(ctx context.Context, newIndexes []*model.Index)) *DataCoordCatalog_AlterIndexes_Call {
_c.Call.Run(func(args mock.Arguments) {
run(args[0].(context.Context), args[1].([]*model.Index))
})
return _c
}
func (_c *DataCoordCatalog_AlterIndexes_Call) Return(_a0 error) *DataCoordCatalog_AlterIndexes_Call {
_c.Call.Return(_a0)
return _c
}
// AlterSegment provides a mock function with given fields: ctx, newSegment, oldSegment
func (_m *DataCoordCatalog) AlterSegment(ctx context.Context, newSegment *datapb.SegmentInfo, oldSegment *datapb.SegmentInfo) error {
ret := _m.Called(ctx, newSegment, oldSegment)
@ -160,9 +82,9 @@ type DataCoordCatalog_AlterSegment_Call struct {
}
// AlterSegment is a helper method to define mock.On call
// - ctx context.Context
// - newSegment *datapb.SegmentInfo
// - oldSegment *datapb.SegmentInfo
// - ctx context.Context
// - newSegment *datapb.SegmentInfo
// - oldSegment *datapb.SegmentInfo
func (_e *DataCoordCatalog_Expecter) AlterSegment(ctx interface{}, newSegment interface{}, oldSegment interface{}) *DataCoordCatalog_AlterSegment_Call {
return &DataCoordCatalog_AlterSegment_Call{Call: _e.mock.On("AlterSegment", ctx, newSegment, oldSegment)}
}
@ -179,82 +101,6 @@ func (_c *DataCoordCatalog_AlterSegment_Call) Return(_a0 error) *DataCoordCatalo
return _c
}
// AlterSegmentIndex provides a mock function with given fields: ctx, newSegIndex
func (_m *DataCoordCatalog) AlterSegmentIndex(ctx context.Context, newSegIndex *model.SegmentIndex) error {
ret := _m.Called(ctx, newSegIndex)
var r0 error
if rf, ok := ret.Get(0).(func(context.Context, *model.SegmentIndex) error); ok {
r0 = rf(ctx, newSegIndex)
} else {
r0 = ret.Error(0)
}
return r0
}
// DataCoordCatalog_AlterSegmentIndex_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'AlterSegmentIndex'
type DataCoordCatalog_AlterSegmentIndex_Call struct {
*mock.Call
}
// AlterSegmentIndex is a helper method to define mock.On call
// - ctx context.Context
// - newSegIndex *model.SegmentIndex
func (_e *DataCoordCatalog_Expecter) AlterSegmentIndex(ctx interface{}, newSegIndex interface{}) *DataCoordCatalog_AlterSegmentIndex_Call {
return &DataCoordCatalog_AlterSegmentIndex_Call{Call: _e.mock.On("AlterSegmentIndex", ctx, newSegIndex)}
}
func (_c *DataCoordCatalog_AlterSegmentIndex_Call) Run(run func(ctx context.Context, newSegIndex *model.SegmentIndex)) *DataCoordCatalog_AlterSegmentIndex_Call {
_c.Call.Run(func(args mock.Arguments) {
run(args[0].(context.Context), args[1].(*model.SegmentIndex))
})
return _c
}
func (_c *DataCoordCatalog_AlterSegmentIndex_Call) Return(_a0 error) *DataCoordCatalog_AlterSegmentIndex_Call {
_c.Call.Return(_a0)
return _c
}
// AlterSegmentIndexes provides a mock function with given fields: ctx, newSegIdxes
func (_m *DataCoordCatalog) AlterSegmentIndexes(ctx context.Context, newSegIdxes []*model.SegmentIndex) error {
ret := _m.Called(ctx, newSegIdxes)
var r0 error
if rf, ok := ret.Get(0).(func(context.Context, []*model.SegmentIndex) error); ok {
r0 = rf(ctx, newSegIdxes)
} else {
r0 = ret.Error(0)
}
return r0
}
// DataCoordCatalog_AlterSegmentIndexes_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'AlterSegmentIndexes'
type DataCoordCatalog_AlterSegmentIndexes_Call struct {
*mock.Call
}
// AlterSegmentIndexes is a helper method to define mock.On call
// - ctx context.Context
// - newSegIdxes []*model.SegmentIndex
func (_e *DataCoordCatalog_Expecter) AlterSegmentIndexes(ctx interface{}, newSegIdxes interface{}) *DataCoordCatalog_AlterSegmentIndexes_Call {
return &DataCoordCatalog_AlterSegmentIndexes_Call{Call: _e.mock.On("AlterSegmentIndexes", ctx, newSegIdxes)}
}
func (_c *DataCoordCatalog_AlterSegmentIndexes_Call) Run(run func(ctx context.Context, newSegIdxes []*model.SegmentIndex)) *DataCoordCatalog_AlterSegmentIndexes_Call {
_c.Call.Run(func(args mock.Arguments) {
run(args[0].(context.Context), args[1].([]*model.SegmentIndex))
})
return _c
}
func (_c *DataCoordCatalog_AlterSegmentIndexes_Call) Return(_a0 error) *DataCoordCatalog_AlterSegmentIndexes_Call {
_c.Call.Return(_a0)
return _c
}
// AlterSegments provides a mock function with given fields: ctx, newSegments
func (_m *DataCoordCatalog) AlterSegments(ctx context.Context, newSegments []*datapb.SegmentInfo) error {
ret := _m.Called(ctx, newSegments)
@ -275,8 +121,8 @@ type DataCoordCatalog_AlterSegments_Call struct {
}
// AlterSegments is a helper method to define mock.On call
// - ctx context.Context
// - newSegments []*datapb.SegmentInfo
// - ctx context.Context
// - newSegments []*datapb.SegmentInfo
func (_e *DataCoordCatalog_Expecter) AlterSegments(ctx interface{}, newSegments interface{}) *DataCoordCatalog_AlterSegments_Call {
return &DataCoordCatalog_AlterSegments_Call{Call: _e.mock.On("AlterSegments", ctx, newSegments)}
}
@ -313,9 +159,9 @@ type DataCoordCatalog_AlterSegmentsAndAddNewSegment_Call struct {
}
// AlterSegmentsAndAddNewSegment is a helper method to define mock.On call
// - ctx context.Context
// - segments []*datapb.SegmentInfo
// - newSegment *datapb.SegmentInfo
// - ctx context.Context
// - segments []*datapb.SegmentInfo
// - newSegment *datapb.SegmentInfo
func (_e *DataCoordCatalog_Expecter) AlterSegmentsAndAddNewSegment(ctx interface{}, segments interface{}, newSegment interface{}) *DataCoordCatalog_AlterSegmentsAndAddNewSegment_Call {
return &DataCoordCatalog_AlterSegmentsAndAddNewSegment_Call{Call: _e.mock.On("AlterSegmentsAndAddNewSegment", ctx, segments, newSegment)}
}
@ -332,82 +178,6 @@ func (_c *DataCoordCatalog_AlterSegmentsAndAddNewSegment_Call) Return(_a0 error)
return _c
}
// CreateIndex provides a mock function with given fields: ctx, index
func (_m *DataCoordCatalog) CreateIndex(ctx context.Context, index *model.Index) error {
ret := _m.Called(ctx, index)
var r0 error
if rf, ok := ret.Get(0).(func(context.Context, *model.Index) error); ok {
r0 = rf(ctx, index)
} else {
r0 = ret.Error(0)
}
return r0
}
// DataCoordCatalog_CreateIndex_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'CreateIndex'
type DataCoordCatalog_CreateIndex_Call struct {
*mock.Call
}
// CreateIndex is a helper method to define mock.On call
// - ctx context.Context
// - index *model.Index
func (_e *DataCoordCatalog_Expecter) CreateIndex(ctx interface{}, index interface{}) *DataCoordCatalog_CreateIndex_Call {
return &DataCoordCatalog_CreateIndex_Call{Call: _e.mock.On("CreateIndex", ctx, index)}
}
func (_c *DataCoordCatalog_CreateIndex_Call) Run(run func(ctx context.Context, index *model.Index)) *DataCoordCatalog_CreateIndex_Call {
_c.Call.Run(func(args mock.Arguments) {
run(args[0].(context.Context), args[1].(*model.Index))
})
return _c
}
func (_c *DataCoordCatalog_CreateIndex_Call) Return(_a0 error) *DataCoordCatalog_CreateIndex_Call {
_c.Call.Return(_a0)
return _c
}
// CreateSegmentIndex provides a mock function with given fields: ctx, segIdx
func (_m *DataCoordCatalog) CreateSegmentIndex(ctx context.Context, segIdx *model.SegmentIndex) error {
ret := _m.Called(ctx, segIdx)
var r0 error
if rf, ok := ret.Get(0).(func(context.Context, *model.SegmentIndex) error); ok {
r0 = rf(ctx, segIdx)
} else {
r0 = ret.Error(0)
}
return r0
}
// DataCoordCatalog_CreateSegmentIndex_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'CreateSegmentIndex'
type DataCoordCatalog_CreateSegmentIndex_Call struct {
*mock.Call
}
// CreateSegmentIndex is a helper method to define mock.On call
// - ctx context.Context
// - segIdx *model.SegmentIndex
func (_e *DataCoordCatalog_Expecter) CreateSegmentIndex(ctx interface{}, segIdx interface{}) *DataCoordCatalog_CreateSegmentIndex_Call {
return &DataCoordCatalog_CreateSegmentIndex_Call{Call: _e.mock.On("CreateSegmentIndex", ctx, segIdx)}
}
func (_c *DataCoordCatalog_CreateSegmentIndex_Call) Run(run func(ctx context.Context, segIdx *model.SegmentIndex)) *DataCoordCatalog_CreateSegmentIndex_Call {
_c.Call.Run(func(args mock.Arguments) {
run(args[0].(context.Context), args[1].(*model.SegmentIndex))
})
return _c
}
func (_c *DataCoordCatalog_CreateSegmentIndex_Call) Return(_a0 error) *DataCoordCatalog_CreateSegmentIndex_Call {
_c.Call.Return(_a0)
return _c
}
// DropChannel provides a mock function with given fields: ctx, channel
func (_m *DataCoordCatalog) DropChannel(ctx context.Context, channel string) error {
ret := _m.Called(ctx, channel)
@ -428,8 +198,8 @@ type DataCoordCatalog_DropChannel_Call struct {
}
// DropChannel is a helper method to define mock.On call
// - ctx context.Context
// - channel string
// - ctx context.Context
// - channel string
func (_e *DataCoordCatalog_Expecter) DropChannel(ctx interface{}, channel interface{}) *DataCoordCatalog_DropChannel_Call {
return &DataCoordCatalog_DropChannel_Call{Call: _e.mock.On("DropChannel", ctx, channel)}
}
@ -466,8 +236,8 @@ type DataCoordCatalog_DropChannelCheckpoint_Call struct {
}
// DropChannelCheckpoint is a helper method to define mock.On call
// - ctx context.Context
// - vChannel string
// - ctx context.Context
// - vChannel string
func (_e *DataCoordCatalog_Expecter) DropChannelCheckpoint(ctx interface{}, vChannel interface{}) *DataCoordCatalog_DropChannelCheckpoint_Call {
return &DataCoordCatalog_DropChannelCheckpoint_Call{Call: _e.mock.On("DropChannelCheckpoint", ctx, vChannel)}
}
@ -484,45 +254,6 @@ func (_c *DataCoordCatalog_DropChannelCheckpoint_Call) Return(_a0 error) *DataCo
return _c
}
// DropIndex provides a mock function with given fields: ctx, collID, dropIdxID
func (_m *DataCoordCatalog) DropIndex(ctx context.Context, collID int64, dropIdxID int64) error {
ret := _m.Called(ctx, collID, dropIdxID)
var r0 error
if rf, ok := ret.Get(0).(func(context.Context, int64, int64) error); ok {
r0 = rf(ctx, collID, dropIdxID)
} else {
r0 = ret.Error(0)
}
return r0
}
// DataCoordCatalog_DropIndex_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'DropIndex'
type DataCoordCatalog_DropIndex_Call struct {
*mock.Call
}
// DropIndex is a helper method to define mock.On call
// - ctx context.Context
// - collID int64
// - dropIdxID int64
func (_e *DataCoordCatalog_Expecter) DropIndex(ctx interface{}, collID interface{}, dropIdxID interface{}) *DataCoordCatalog_DropIndex_Call {
return &DataCoordCatalog_DropIndex_Call{Call: _e.mock.On("DropIndex", ctx, collID, dropIdxID)}
}
func (_c *DataCoordCatalog_DropIndex_Call) Run(run func(ctx context.Context, collID int64, dropIdxID int64)) *DataCoordCatalog_DropIndex_Call {
_c.Call.Run(func(args mock.Arguments) {
run(args[0].(context.Context), args[1].(int64), args[2].(int64))
})
return _c
}
func (_c *DataCoordCatalog_DropIndex_Call) Return(_a0 error) *DataCoordCatalog_DropIndex_Call {
_c.Call.Return(_a0)
return _c
}
// DropSegment provides a mock function with given fields: ctx, segment
func (_m *DataCoordCatalog) DropSegment(ctx context.Context, segment *datapb.SegmentInfo) error {
ret := _m.Called(ctx, segment)
@ -543,8 +274,8 @@ type DataCoordCatalog_DropSegment_Call struct {
}
// DropSegment is a helper method to define mock.On call
// - ctx context.Context
// - segment *datapb.SegmentInfo
// - ctx context.Context
// - segment *datapb.SegmentInfo
func (_e *DataCoordCatalog_Expecter) DropSegment(ctx interface{}, segment interface{}) *DataCoordCatalog_DropSegment_Call {
return &DataCoordCatalog_DropSegment_Call{Call: _e.mock.On("DropSegment", ctx, segment)}
}
@ -561,43 +292,41 @@ func (_c *DataCoordCatalog_DropSegment_Call) Return(_a0 error) *DataCoordCatalog
return _c
}
// DropSegmentIndex provides a mock function with given fields: ctx, collID, partID, segID, buildID
func (_m *DataCoordCatalog) DropSegmentIndex(ctx context.Context, collID int64, partID int64, segID int64, buildID int64) error {
ret := _m.Called(ctx, collID, partID, segID, buildID)
// GcConfirm provides a mock function with given fields: ctx, collectionID, partitionID
func (_m *DataCoordCatalog) GcConfirm(ctx context.Context, collectionID int64, partitionID int64) bool {
ret := _m.Called(ctx, collectionID, partitionID)
var r0 error
if rf, ok := ret.Get(0).(func(context.Context, int64, int64, int64, int64) error); ok {
r0 = rf(ctx, collID, partID, segID, buildID)
var r0 bool
if rf, ok := ret.Get(0).(func(context.Context, int64, int64) bool); ok {
r0 = rf(ctx, collectionID, partitionID)
} else {
r0 = ret.Error(0)
r0 = ret.Get(0).(bool)
}
return r0
}
// DataCoordCatalog_DropSegmentIndex_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'DropSegmentIndex'
type DataCoordCatalog_DropSegmentIndex_Call struct {
// DataCoordCatalog_GcConfirm_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'GcConfirm'
type DataCoordCatalog_GcConfirm_Call struct {
*mock.Call
}
// DropSegmentIndex is a helper method to define mock.On call
// - ctx context.Context
// - collID int64
// - partID int64
// - segID int64
// - buildID int64
func (_e *DataCoordCatalog_Expecter) DropSegmentIndex(ctx interface{}, collID interface{}, partID interface{}, segID interface{}, buildID interface{}) *DataCoordCatalog_DropSegmentIndex_Call {
return &DataCoordCatalog_DropSegmentIndex_Call{Call: _e.mock.On("DropSegmentIndex", ctx, collID, partID, segID, buildID)}
// GcConfirm is a helper method to define mock.On call
// - ctx context.Context
// - collectionID int64
// - partitionID int64
func (_e *DataCoordCatalog_Expecter) GcConfirm(ctx interface{}, collectionID interface{}, partitionID interface{}) *DataCoordCatalog_GcConfirm_Call {
return &DataCoordCatalog_GcConfirm_Call{Call: _e.mock.On("GcConfirm", ctx, collectionID, partitionID)}
}
func (_c *DataCoordCatalog_DropSegmentIndex_Call) Run(run func(ctx context.Context, collID int64, partID int64, segID int64, buildID int64)) *DataCoordCatalog_DropSegmentIndex_Call {
func (_c *DataCoordCatalog_GcConfirm_Call) Run(run func(ctx context.Context, collectionID int64, partitionID int64)) *DataCoordCatalog_GcConfirm_Call {
_c.Call.Run(func(args mock.Arguments) {
run(args[0].(context.Context), args[1].(int64), args[2].(int64), args[3].(int64), args[4].(int64))
run(args[0].(context.Context), args[1].(int64), args[2].(int64))
})
return _c
}
func (_c *DataCoordCatalog_DropSegmentIndex_Call) Return(_a0 error) *DataCoordCatalog_DropSegmentIndex_Call {
func (_c *DataCoordCatalog_GcConfirm_Call) Return(_a0 bool) *DataCoordCatalog_GcConfirm_Call {
_c.Call.Return(_a0)
return _c
}
@ -622,8 +351,8 @@ type DataCoordCatalog_IsChannelDropped_Call struct {
}
// IsChannelDropped is a helper method to define mock.On call
// - ctx context.Context
// - channel string
// - ctx context.Context
// - channel string
func (_e *DataCoordCatalog_Expecter) IsChannelDropped(ctx interface{}, channel interface{}) *DataCoordCatalog_IsChannelDropped_Call {
return &DataCoordCatalog_IsChannelDropped_Call{Call: _e.mock.On("IsChannelDropped", ctx, channel)}
}
@ -669,7 +398,7 @@ type DataCoordCatalog_ListChannelCheckpoint_Call struct {
}
// ListChannelCheckpoint is a helper method to define mock.On call
// - ctx context.Context
// - ctx context.Context
func (_e *DataCoordCatalog_Expecter) ListChannelCheckpoint(ctx interface{}) *DataCoordCatalog_ListChannelCheckpoint_Call {
return &DataCoordCatalog_ListChannelCheckpoint_Call{Call: _e.mock.On("ListChannelCheckpoint", ctx)}
}
@ -686,98 +415,6 @@ func (_c *DataCoordCatalog_ListChannelCheckpoint_Call) Return(_a0 map[string]*in
return _c
}
// ListIndexes provides a mock function with given fields: ctx
func (_m *DataCoordCatalog) ListIndexes(ctx context.Context) ([]*model.Index, error) {
ret := _m.Called(ctx)
var r0 []*model.Index
if rf, ok := ret.Get(0).(func(context.Context) []*model.Index); ok {
r0 = rf(ctx)
} else {
if ret.Get(0) != nil {
r0 = ret.Get(0).([]*model.Index)
}
}
var r1 error
if rf, ok := ret.Get(1).(func(context.Context) error); ok {
r1 = rf(ctx)
} else {
r1 = ret.Error(1)
}
return r0, r1
}
// DataCoordCatalog_ListIndexes_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'ListIndexes'
type DataCoordCatalog_ListIndexes_Call struct {
*mock.Call
}
// ListIndexes is a helper method to define mock.On call
// - ctx context.Context
func (_e *DataCoordCatalog_Expecter) ListIndexes(ctx interface{}) *DataCoordCatalog_ListIndexes_Call {
return &DataCoordCatalog_ListIndexes_Call{Call: _e.mock.On("ListIndexes", ctx)}
}
func (_c *DataCoordCatalog_ListIndexes_Call) Run(run func(ctx context.Context)) *DataCoordCatalog_ListIndexes_Call {
_c.Call.Run(func(args mock.Arguments) {
run(args[0].(context.Context))
})
return _c
}
func (_c *DataCoordCatalog_ListIndexes_Call) Return(_a0 []*model.Index, _a1 error) *DataCoordCatalog_ListIndexes_Call {
_c.Call.Return(_a0, _a1)
return _c
}
// ListSegmentIndexes provides a mock function with given fields: ctx
func (_m *DataCoordCatalog) ListSegmentIndexes(ctx context.Context) ([]*model.SegmentIndex, error) {
ret := _m.Called(ctx)
var r0 []*model.SegmentIndex
if rf, ok := ret.Get(0).(func(context.Context) []*model.SegmentIndex); ok {
r0 = rf(ctx)
} else {
if ret.Get(0) != nil {
r0 = ret.Get(0).([]*model.SegmentIndex)
}
}
var r1 error
if rf, ok := ret.Get(1).(func(context.Context) error); ok {
r1 = rf(ctx)
} else {
r1 = ret.Error(1)
}
return r0, r1
}
// DataCoordCatalog_ListSegmentIndexes_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'ListSegmentIndexes'
type DataCoordCatalog_ListSegmentIndexes_Call struct {
*mock.Call
}
// ListSegmentIndexes is a helper method to define mock.On call
// - ctx context.Context
func (_e *DataCoordCatalog_Expecter) ListSegmentIndexes(ctx interface{}) *DataCoordCatalog_ListSegmentIndexes_Call {
return &DataCoordCatalog_ListSegmentIndexes_Call{Call: _e.mock.On("ListSegmentIndexes", ctx)}
}
func (_c *DataCoordCatalog_ListSegmentIndexes_Call) Run(run func(ctx context.Context)) *DataCoordCatalog_ListSegmentIndexes_Call {
_c.Call.Run(func(args mock.Arguments) {
run(args[0].(context.Context))
})
return _c
}
func (_c *DataCoordCatalog_ListSegmentIndexes_Call) Return(_a0 []*model.SegmentIndex, _a1 error) *DataCoordCatalog_ListSegmentIndexes_Call {
_c.Call.Return(_a0, _a1)
return _c
}
// ListSegments provides a mock function with given fields: ctx
func (_m *DataCoordCatalog) ListSegments(ctx context.Context) ([]*datapb.SegmentInfo, error) {
ret := _m.Called(ctx)
@ -807,7 +444,7 @@ type DataCoordCatalog_ListSegments_Call struct {
}
// ListSegments is a helper method to define mock.On call
// - ctx context.Context
// - ctx context.Context
func (_e *DataCoordCatalog_Expecter) ListSegments(ctx interface{}) *DataCoordCatalog_ListSegments_Call {
return &DataCoordCatalog_ListSegments_Call{Call: _e.mock.On("ListSegments", ctx)}
}
@ -844,8 +481,8 @@ type DataCoordCatalog_MarkChannelDeleted_Call struct {
}
// MarkChannelDeleted is a helper method to define mock.On call
// - ctx context.Context
// - channel string
// - ctx context.Context
// - channel string
func (_e *DataCoordCatalog_Expecter) MarkChannelDeleted(ctx interface{}, channel interface{}) *DataCoordCatalog_MarkChannelDeleted_Call {
return &DataCoordCatalog_MarkChannelDeleted_Call{Call: _e.mock.On("MarkChannelDeleted", ctx, channel)}
}
@ -882,9 +519,9 @@ type DataCoordCatalog_RevertAlterSegmentsAndAddNewSegment_Call struct {
}
// RevertAlterSegmentsAndAddNewSegment is a helper method to define mock.On call
// - ctx context.Context
// - segments []*datapb.SegmentInfo
// - removalSegment *datapb.SegmentInfo
// - ctx context.Context
// - segments []*datapb.SegmentInfo
// - removalSegment *datapb.SegmentInfo
func (_e *DataCoordCatalog_Expecter) RevertAlterSegmentsAndAddNewSegment(ctx interface{}, segments interface{}, removalSegment interface{}) *DataCoordCatalog_RevertAlterSegmentsAndAddNewSegment_Call {
return &DataCoordCatalog_RevertAlterSegmentsAndAddNewSegment_Call{Call: _e.mock.On("RevertAlterSegmentsAndAddNewSegment", ctx, segments, removalSegment)}
}
@ -921,9 +558,9 @@ type DataCoordCatalog_SaveChannelCheckpoint_Call struct {
}
// SaveChannelCheckpoint is a helper method to define mock.On call
// - ctx context.Context
// - vChannel string
// - pos *internalpb.MsgPosition
// - ctx context.Context
// - vChannel string
// - pos *internalpb.MsgPosition
func (_e *DataCoordCatalog_Expecter) SaveChannelCheckpoint(ctx interface{}, vChannel interface{}, pos interface{}) *DataCoordCatalog_SaveChannelCheckpoint_Call {
return &DataCoordCatalog_SaveChannelCheckpoint_Call{Call: _e.mock.On("SaveChannelCheckpoint", ctx, vChannel, pos)}
}
@ -960,8 +597,8 @@ type DataCoordCatalog_SaveDroppedSegmentsInBatch_Call struct {
}
// SaveDroppedSegmentsInBatch is a helper method to define mock.On call
// - ctx context.Context
// - segments []*datapb.SegmentInfo
// - ctx context.Context
// - segments []*datapb.SegmentInfo
func (_e *DataCoordCatalog_Expecter) SaveDroppedSegmentsInBatch(ctx interface{}, segments interface{}) *DataCoordCatalog_SaveDroppedSegmentsInBatch_Call {
return &DataCoordCatalog_SaveDroppedSegmentsInBatch_Call{Call: _e.mock.On("SaveDroppedSegmentsInBatch", ctx, segments)}
}

View File

@ -1,4 +1,4 @@
// Code generated by mockery v2.14.0. DO NOT EDIT.
// Code generated by mockery v2.16.0. DO NOT EDIT.
package mocks

View File

@ -311,6 +311,53 @@ func (_c *DataCoord_Flush_Call) Return(_a0 *datapb.FlushResponse, _a1 error) *Da
return _c
}
// GcConfirm provides a mock function with given fields: ctx, request
func (_m *DataCoord) GcConfirm(ctx context.Context, request *datapb.GcConfirmRequest) (*datapb.GcConfirmResponse, error) {
ret := _m.Called(ctx, request)
var r0 *datapb.GcConfirmResponse
if rf, ok := ret.Get(0).(func(context.Context, *datapb.GcConfirmRequest) *datapb.GcConfirmResponse); ok {
r0 = rf(ctx, request)
} else {
if ret.Get(0) != nil {
r0 = ret.Get(0).(*datapb.GcConfirmResponse)
}
}
var r1 error
if rf, ok := ret.Get(1).(func(context.Context, *datapb.GcConfirmRequest) error); ok {
r1 = rf(ctx, request)
} else {
r1 = ret.Error(1)
}
return r0, r1
}
// DataCoord_GcConfirm_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'GcConfirm'
type DataCoord_GcConfirm_Call struct {
*mock.Call
}
// GcConfirm is a helper method to define mock.On call
// - ctx context.Context
// - request *datapb.GcConfirmRequest
func (_e *DataCoord_Expecter) GcConfirm(ctx interface{}, request interface{}) *DataCoord_GcConfirm_Call {
return &DataCoord_GcConfirm_Call{Call: _e.mock.On("GcConfirm", ctx, request)}
}
func (_c *DataCoord_GcConfirm_Call) Run(run func(ctx context.Context, request *datapb.GcConfirmRequest)) *DataCoord_GcConfirm_Call {
_c.Call.Run(func(args mock.Arguments) {
run(args[0].(context.Context), args[1].(*datapb.GcConfirmRequest))
})
return _c
}
func (_c *DataCoord_GcConfirm_Call) Return(_a0 *datapb.GcConfirmResponse, _a1 error) *DataCoord_GcConfirm_Call {
_c.Call.Return(_a0, _a1)
return _c
}
// GetCollectionStatistics provides a mock function with given fields: ctx, req
func (_m *DataCoord) GetCollectionStatistics(ctx context.Context, req *datapb.GetCollectionStatisticsRequest) (*datapb.GetCollectionStatisticsResponse, error) {
ret := _m.Called(ctx, req)

File diff suppressed because it is too large Load Diff

View File

@ -69,6 +69,8 @@ service DataCoord {
rpc BroadcastAlteredCollection(AlterCollectionRequest) returns (common.Status) {}
rpc CheckHealth(milvus.CheckHealthRequest) returns (milvus.CheckHealthResponse) {}
rpc GcConfirm(GcConfirmRequest) returns (GcConfirmResponse) {}
}
service DataNode {
@ -645,3 +647,13 @@ message AlterCollectionRequest {
repeated common.KeyDataPair start_positions = 4;
repeated common.KeyValuePair properties = 5;
}
message GcConfirmRequest {
int64 collection_id = 1;
int64 partition_id = 2; // -1 means whole collection.
}
message GcConfirmResponse {
common.Status status = 1;
bool gc_finished = 2;
}

View File

@ -4882,6 +4882,100 @@ func (m *AlterCollectionRequest) GetProperties() []*commonpb.KeyValuePair {
return nil
}
type GcConfirmRequest struct {
CollectionId int64 `protobuf:"varint,1,opt,name=collection_id,json=collectionId,proto3" json:"collection_id,omitempty"`
PartitionId int64 `protobuf:"varint,2,opt,name=partition_id,json=partitionId,proto3" json:"partition_id,omitempty"`
XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"`
XXX_sizecache int32 `json:"-"`
}
func (m *GcConfirmRequest) Reset() { *m = GcConfirmRequest{} }
func (m *GcConfirmRequest) String() string { return proto.CompactTextString(m) }
func (*GcConfirmRequest) ProtoMessage() {}
func (*GcConfirmRequest) Descriptor() ([]byte, []int) {
return fileDescriptor_82cd95f524594f49, []int{76}
}
func (m *GcConfirmRequest) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_GcConfirmRequest.Unmarshal(m, b)
}
func (m *GcConfirmRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
return xxx_messageInfo_GcConfirmRequest.Marshal(b, m, deterministic)
}
func (m *GcConfirmRequest) XXX_Merge(src proto.Message) {
xxx_messageInfo_GcConfirmRequest.Merge(m, src)
}
func (m *GcConfirmRequest) XXX_Size() int {
return xxx_messageInfo_GcConfirmRequest.Size(m)
}
func (m *GcConfirmRequest) XXX_DiscardUnknown() {
xxx_messageInfo_GcConfirmRequest.DiscardUnknown(m)
}
var xxx_messageInfo_GcConfirmRequest proto.InternalMessageInfo
func (m *GcConfirmRequest) GetCollectionId() int64 {
if m != nil {
return m.CollectionId
}
return 0
}
func (m *GcConfirmRequest) GetPartitionId() int64 {
if m != nil {
return m.PartitionId
}
return 0
}
type GcConfirmResponse struct {
Status *commonpb.Status `protobuf:"bytes,1,opt,name=status,proto3" json:"status,omitempty"`
GcFinished bool `protobuf:"varint,2,opt,name=gc_finished,json=gcFinished,proto3" json:"gc_finished,omitempty"`
XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"`
XXX_sizecache int32 `json:"-"`
}
func (m *GcConfirmResponse) Reset() { *m = GcConfirmResponse{} }
func (m *GcConfirmResponse) String() string { return proto.CompactTextString(m) }
func (*GcConfirmResponse) ProtoMessage() {}
func (*GcConfirmResponse) Descriptor() ([]byte, []int) {
return fileDescriptor_82cd95f524594f49, []int{77}
}
func (m *GcConfirmResponse) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_GcConfirmResponse.Unmarshal(m, b)
}
func (m *GcConfirmResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
return xxx_messageInfo_GcConfirmResponse.Marshal(b, m, deterministic)
}
func (m *GcConfirmResponse) XXX_Merge(src proto.Message) {
xxx_messageInfo_GcConfirmResponse.Merge(m, src)
}
func (m *GcConfirmResponse) XXX_Size() int {
return xxx_messageInfo_GcConfirmResponse.Size(m)
}
func (m *GcConfirmResponse) XXX_DiscardUnknown() {
xxx_messageInfo_GcConfirmResponse.DiscardUnknown(m)
}
var xxx_messageInfo_GcConfirmResponse proto.InternalMessageInfo
func (m *GcConfirmResponse) GetStatus() *commonpb.Status {
if m != nil {
return m.Status
}
return nil
}
func (m *GcConfirmResponse) GetGcFinished() bool {
if m != nil {
return m.GcFinished
}
return false
}
func init() {
proto.RegisterEnum("milvus.proto.data.SegmentType", SegmentType_name, SegmentType_value)
proto.RegisterEnum("milvus.proto.data.ChannelWatchState", ChannelWatchState_name, ChannelWatchState_value)
@ -4963,292 +5057,298 @@ func init() {
proto.RegisterType((*MarkSegmentsDroppedRequest)(nil), "milvus.proto.data.MarkSegmentsDroppedRequest")
proto.RegisterType((*SegmentReferenceLock)(nil), "milvus.proto.data.SegmentReferenceLock")
proto.RegisterType((*AlterCollectionRequest)(nil), "milvus.proto.data.AlterCollectionRequest")
proto.RegisterType((*GcConfirmRequest)(nil), "milvus.proto.data.GcConfirmRequest")
proto.RegisterType((*GcConfirmResponse)(nil), "milvus.proto.data.GcConfirmResponse")
}
func init() { proto.RegisterFile("data_coord.proto", fileDescriptor_82cd95f524594f49) }
var fileDescriptor_82cd95f524594f49 = []byte{
// 4479 bytes of a gzipped FileDescriptorProto
// 4542 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe4, 0x3c, 0x4b, 0x8c, 0x1c, 0x49,
0x56, 0xce, 0xfa, 0x75, 0xd5, 0xab, 0x4f, 0x57, 0x87, 0x3d, 0xed, 0x72, 0xf9, 0x3b, 0xe9, 0xf1,
0x8c, 0xc7, 0xe3, 0xb1, 0x67, 0x7a, 0x18, 0xad, 0x59, 0xef, 0xcc, 0xe2, 0xee, 0x76, 0x7b, 0x0a,
0xba, 0x7b, 0x7b, 0xb3, 0xdb, 0x63, 0x69, 0x17, 0xa9, 0x94, 0x5d, 0x19, 0x5d, 0x9d, 0xdb, 0x55,
0x99, 0xe5, 0xcc, 0xac, 0x6e, 0xf7, 0x72, 0xd8, 0x11, 0x48, 0xa0, 0x45, 0x88, 0x45, 0x48, 0x08,
0x38, 0x20, 0x21, 0x4e, 0xcb, 0xa2, 0x45, 0x48, 0x2b, 0x2e, 0x5c, 0xb8, 0x8e, 0xe0, 0x30, 0x42,
0x48, 0x1c, 0x39, 0x70, 0x00, 0xee, 0x5c, 0x39, 0xa0, 0xf8, 0x64, 0xe4, 0x2f, 0xb2, 0x2a, 0xbb,
0xca, 0x1e, 0x23, 0xb8, 0x55, 0x44, 0xbe, 0x78, 0x2f, 0x3e, 0xef, 0x1f, 0x2f, 0x0a, 0x9a, 0x86,
0xee, 0xe9, 0xdd, 0x9e, 0x6d, 0x3b, 0xc6, 0xbd, 0x91, 0x63, 0x7b, 0x36, 0x5a, 0x1a, 0x9a, 0x83,
0xe3, 0xb1, 0xcb, 0x5a, 0xf7, 0xc8, 0xe7, 0x76, 0xad, 0x67, 0x0f, 0x87, 0xb6, 0xc5, 0xba, 0xda,
0x0d, 0xd3, 0xf2, 0xb0, 0x63, 0xe9, 0x03, 0xde, 0xae, 0x85, 0x07, 0xb4, 0x6b, 0x6e, 0xef, 0x10,
0x0f, 0x75, 0xd6, 0x52, 0x17, 0xa0, 0xf8, 0x78, 0x38, 0xf2, 0x4e, 0xd5, 0x3f, 0x51, 0xa0, 0xb6,
0x31, 0x18, 0xbb, 0x87, 0x1a, 0x7e, 0x3e, 0xc6, 0xae, 0x87, 0x3e, 0x80, 0xc2, 0xbe, 0xee, 0xe2,
0x96, 0x72, 0x43, 0xb9, 0x5d, 0x5d, 0xb9, 0x72, 0x2f, 0x42, 0x95, 0xd3, 0xdb, 0x72, 0xfb, 0xab,
0xba, 0x8b, 0x35, 0x0a, 0x89, 0x10, 0x14, 0x8c, 0xfd, 0xce, 0x7a, 0x2b, 0x77, 0x43, 0xb9, 0x9d,
0xd7, 0xe8, 0x6f, 0x74, 0x0d, 0xc0, 0xc5, 0xfd, 0x21, 0xb6, 0xbc, 0xce, 0xba, 0xdb, 0xca, 0xdf,
0xc8, 0xdf, 0xce, 0x6b, 0xa1, 0x1e, 0xa4, 0x42, 0xad, 0x67, 0x0f, 0x06, 0xb8, 0xe7, 0x99, 0xb6,
0xd5, 0x59, 0x6f, 0x15, 0xe8, 0xd8, 0x48, 0x9f, 0xfa, 0xef, 0x0a, 0xd4, 0xf9, 0xd4, 0xdc, 0x91,
0x6d, 0xb9, 0x18, 0x7d, 0x04, 0x25, 0xd7, 0xd3, 0xbd, 0xb1, 0xcb, 0x67, 0x77, 0x59, 0x3a, 0xbb,
0x5d, 0x0a, 0xa2, 0x71, 0x50, 0xe9, 0xf4, 0xe2, 0xe4, 0xf3, 0x49, 0xf2, 0xb1, 0x25, 0x14, 0x12,
0x4b, 0xb8, 0x0d, 0x8b, 0x07, 0x64, 0x76, 0xbb, 0x01, 0x50, 0x91, 0x02, 0xc5, 0xbb, 0x09, 0x26,
0xcf, 0x1c, 0xe2, 0xef, 0x1c, 0xec, 0x62, 0x7d, 0xd0, 0x2a, 0x51, 0x5a, 0xa1, 0x1e, 0xf5, 0x9f,
0x14, 0x68, 0x0a, 0x70, 0xff, 0x1c, 0x2e, 0x40, 0xb1, 0x67, 0x8f, 0x2d, 0x8f, 0x2e, 0xb5, 0xae,
0xb1, 0x06, 0x7a, 0x13, 0x6a, 0xbd, 0x43, 0xdd, 0xb2, 0xf0, 0xa0, 0x6b, 0xe9, 0x43, 0x4c, 0x17,
0x55, 0xd1, 0xaa, 0xbc, 0x6f, 0x5b, 0x1f, 0xe2, 0x4c, 0x6b, 0xbb, 0x01, 0xd5, 0x91, 0xee, 0x78,
0x66, 0x64, 0xf7, 0xc3, 0x5d, 0xa8, 0x0d, 0x65, 0xd3, 0xed, 0x0c, 0x47, 0xb6, 0xe3, 0xb5, 0x8a,
0x37, 0x94, 0xdb, 0x65, 0x4d, 0xb4, 0x09, 0x05, 0x93, 0xfe, 0xda, 0xd3, 0xdd, 0xa3, 0xce, 0x3a,
0x5f, 0x51, 0xa4, 0x4f, 0xfd, 0x73, 0x05, 0x96, 0x1f, 0xb9, 0xae, 0xd9, 0xb7, 0x12, 0x2b, 0x5b,
0x86, 0x92, 0x65, 0x1b, 0xb8, 0xb3, 0x4e, 0x97, 0x96, 0xd7, 0x78, 0x0b, 0x5d, 0x86, 0xca, 0x08,
0x63, 0xa7, 0xeb, 0xd8, 0x03, 0x7f, 0x61, 0x65, 0xd2, 0xa1, 0xd9, 0x03, 0x8c, 0xbe, 0x0b, 0x4b,
0x6e, 0x0c, 0x11, 0xe3, 0xab, 0xea, 0xca, 0xcd, 0x7b, 0x09, 0xc9, 0xb8, 0x17, 0x27, 0xaa, 0x25,
0x47, 0xab, 0x5f, 0xe4, 0xe0, 0xbc, 0x80, 0x63, 0x73, 0x25, 0xbf, 0xc9, 0xce, 0xbb, 0xb8, 0x2f,
0xa6, 0xc7, 0x1a, 0x59, 0x76, 0x5e, 0x1c, 0x59, 0x3e, 0x7c, 0x64, 0x19, 0x58, 0x3d, 0x7e, 0x1e,
0xc5, 0xe4, 0x79, 0x5c, 0x87, 0x2a, 0x7e, 0x31, 0x32, 0x1d, 0xdc, 0x25, 0x8c, 0x43, 0xb7, 0xbc,
0xa0, 0x01, 0xeb, 0xda, 0x33, 0x87, 0x61, 0xd9, 0x58, 0xc8, 0x2c, 0x1b, 0xea, 0x5f, 0x28, 0x70,
0x31, 0x71, 0x4a, 0x5c, 0xd8, 0x34, 0x68, 0xd2, 0x95, 0x07, 0x3b, 0x43, 0xc4, 0x8e, 0x6c, 0xf8,
0xdb, 0x93, 0x36, 0x3c, 0x00, 0xd7, 0x12, 0xe3, 0x43, 0x93, 0xcc, 0x65, 0x9f, 0xe4, 0x11, 0x5c,
0x7c, 0x82, 0x3d, 0x4e, 0x80, 0x7c, 0xc3, 0xee, 0xec, 0xca, 0x2a, 0x2a, 0xd5, 0xb9, 0xb8, 0x54,
0xab, 0x7f, 0x93, 0x13, 0xb2, 0x48, 0x49, 0x75, 0xac, 0x03, 0x1b, 0x5d, 0x81, 0x8a, 0x00, 0xe1,
0x5c, 0x11, 0x74, 0xa0, 0x6f, 0x40, 0x91, 0xcc, 0x94, 0xb1, 0x44, 0x63, 0xe5, 0x4d, 0xf9, 0x9a,
0x42, 0x38, 0x35, 0x06, 0x8f, 0x3a, 0xd0, 0x70, 0x3d, 0xdd, 0xf1, 0xba, 0x23, 0xdb, 0xa5, 0xe7,
0x4c, 0x19, 0xa7, 0xba, 0xa2, 0x46, 0x31, 0x08, 0xb5, 0xbe, 0xe5, 0xf6, 0x77, 0x38, 0xa4, 0x56,
0xa7, 0x23, 0xfd, 0x26, 0x7a, 0x0c, 0x35, 0x6c, 0x19, 0x01, 0xa2, 0x42, 0x66, 0x44, 0x55, 0x6c,
0x19, 0x02, 0x4d, 0x70, 0x3e, 0xc5, 0xec, 0xe7, 0xf3, 0x7b, 0x0a, 0xb4, 0x92, 0x07, 0x34, 0x8f,
0xca, 0x7e, 0xc8, 0x06, 0x61, 0x76, 0x40, 0x13, 0x25, 0x5c, 0x1c, 0x92, 0xc6, 0x87, 0xa8, 0x7f,
0xa4, 0xc0, 0x1b, 0xc1, 0x74, 0xe8, 0xa7, 0x57, 0xc5, 0x2d, 0xe8, 0x0e, 0x34, 0x4d, 0xab, 0x37,
0x18, 0x1b, 0xf8, 0xa9, 0xf5, 0x19, 0xd6, 0x07, 0xde, 0xe1, 0x29, 0x3d, 0xc3, 0xb2, 0x96, 0xe8,
0x57, 0xff, 0x35, 0x07, 0xcb, 0xf1, 0x79, 0xcd, 0xb3, 0x49, 0xbf, 0x04, 0x45, 0xd3, 0x3a, 0xb0,
0xfd, 0x3d, 0xba, 0x36, 0x41, 0x28, 0x09, 0x2d, 0x06, 0x8c, 0x6c, 0x40, 0xbe, 0x1a, 0xeb, 0x1d,
0xe2, 0xde, 0xd1, 0xc8, 0x36, 0xa9, 0xc2, 0x22, 0x28, 0x7e, 0x45, 0x82, 0x42, 0x3e, 0xe3, 0x7b,
0x6b, 0x0c, 0xc7, 0x9a, 0x40, 0xf1, 0xd8, 0xf2, 0x9c, 0x53, 0x6d, 0xa9, 0x17, 0xef, 0x6f, 0x1f,
0xc2, 0xb2, 0x1c, 0x18, 0x35, 0x21, 0x7f, 0x84, 0x4f, 0xe9, 0x92, 0x2b, 0x1a, 0xf9, 0x89, 0x1e,
0x40, 0xf1, 0x58, 0x1f, 0x8c, 0x31, 0xd7, 0x0e, 0x59, 0xd8, 0x97, 0x0d, 0xf8, 0x66, 0xee, 0x81,
0xa2, 0x0e, 0xe1, 0xf2, 0x13, 0xec, 0x75, 0x2c, 0x17, 0x3b, 0xde, 0xaa, 0x69, 0x0d, 0xec, 0xfe,
0x8e, 0xee, 0x1d, 0xce, 0xa1, 0x2b, 0x22, 0x62, 0x9f, 0x8b, 0x89, 0xbd, 0xfa, 0x53, 0x05, 0xae,
0xc8, 0xe9, 0xf1, 0x53, 0x6d, 0x43, 0xf9, 0xc0, 0xc4, 0x03, 0x83, 0xb0, 0x8e, 0x42, 0x59, 0x47,
0xb4, 0x89, 0xce, 0x18, 0x11, 0x60, 0x7e, 0x78, 0x6f, 0xa6, 0xac, 0x74, 0xd7, 0x73, 0x4c, 0xab,
0xbf, 0x69, 0xba, 0x9e, 0xc6, 0xe0, 0x43, 0xac, 0x92, 0xcf, 0x2e, 0xa1, 0xbf, 0xab, 0xc0, 0xb5,
0x27, 0xd8, 0x5b, 0x13, 0x26, 0x87, 0x7c, 0x37, 0x5d, 0xcf, 0xec, 0xb9, 0x2f, 0xd7, 0xed, 0xcb,
0xe0, 0x7b, 0xa8, 0x3f, 0x51, 0xe0, 0x7a, 0xea, 0x64, 0xf8, 0xd6, 0x71, 0x95, 0xea, 0x1b, 0x1c,
0xb9, 0x4a, 0xfd, 0x35, 0x7c, 0xfa, 0x39, 0x39, 0xfc, 0x1d, 0xdd, 0x74, 0x98, 0x4a, 0x9d, 0xd1,
0xc0, 0xfc, 0x5c, 0x81, 0xab, 0x4f, 0xb0, 0xb7, 0xe3, 0x9b, 0xdb, 0xd7, 0xb8, 0x3b, 0x04, 0x26,
0x64, 0xf6, 0x7d, 0xbf, 0x33, 0xd2, 0xa7, 0xfe, 0x3e, 0x3b, 0x4e, 0xe9, 0x7c, 0x5f, 0xcb, 0x06,
0x5e, 0xa3, 0x92, 0x10, 0xd2, 0x13, 0x5c, 0xe2, 0xf9, 0xf6, 0xa9, 0x7f, 0xa6, 0xc0, 0xa5, 0x47,
0xbd, 0xe7, 0x63, 0xd3, 0xc1, 0x1c, 0x68, 0xd3, 0xee, 0x1d, 0xcd, 0xbe, 0xb9, 0x81, 0x07, 0x99,
0x8b, 0x78, 0x90, 0xd3, 0xa2, 0x8e, 0x65, 0x28, 0x79, 0xcc, 0x65, 0x65, 0x4e, 0x18, 0x6f, 0xd1,
0xf9, 0x69, 0x78, 0x80, 0x75, 0xf7, 0x7f, 0xe7, 0xfc, 0x7e, 0x52, 0x80, 0xda, 0xe7, 0x5c, 0xb5,
0x52, 0x87, 0x24, 0xce, 0x49, 0x8a, 0xdc, 0xa7, 0x0c, 0x39, 0xa7, 0x32, 0x7f, 0xf5, 0x09, 0xd4,
0x5d, 0x8c, 0x8f, 0x66, 0x71, 0x3f, 0x6a, 0x64, 0xa0, 0x70, 0x1b, 0x36, 0x61, 0x69, 0x6c, 0xd1,
0xa8, 0x07, 0x1b, 0x7c, 0x03, 0x19, 0xe7, 0x4e, 0x37, 0x4b, 0xc9, 0x81, 0xe8, 0x33, 0x1e, 0x58,
0x85, 0x70, 0x15, 0x33, 0xe1, 0x8a, 0x0f, 0x43, 0x1d, 0x68, 0x1a, 0x8e, 0x3d, 0x1a, 0x61, 0xa3,
0xeb, 0xfa, 0xa8, 0x4a, 0xd9, 0x50, 0xf1, 0x71, 0x02, 0xd5, 0x07, 0x70, 0x3e, 0x3e, 0xd3, 0x8e,
0x41, 0x7c, 0x6d, 0x72, 0x86, 0xb2, 0x4f, 0xe8, 0x2e, 0x2c, 0x25, 0xe1, 0xcb, 0x14, 0x3e, 0xf9,
0x01, 0xbd, 0x0f, 0x28, 0x36, 0x55, 0x02, 0x5e, 0x61, 0xe0, 0xd1, 0xc9, 0x74, 0x0c, 0x57, 0xfd,
0xb1, 0x02, 0xcb, 0xcf, 0x74, 0xaf, 0x77, 0xb8, 0x3e, 0xe4, 0xb2, 0x36, 0x87, 0xae, 0xfa, 0x04,
0x2a, 0xc7, 0x9c, 0x2f, 0x7c, 0x83, 0x74, 0x5d, 0xb2, 0x3f, 0x61, 0x0e, 0xd4, 0x82, 0x11, 0x24,
0xd4, 0xbb, 0xb0, 0x11, 0x0a, 0x79, 0x5f, 0x83, 0xd6, 0x9c, 0x12, 0xab, 0xab, 0x2f, 0x00, 0xf8,
0xe4, 0xb6, 0xdc, 0xfe, 0x0c, 0xf3, 0x7a, 0x00, 0x0b, 0x1c, 0x1b, 0x57, 0x8b, 0xd3, 0xf8, 0xc7,
0x07, 0x57, 0x7f, 0x56, 0x82, 0x6a, 0xe8, 0x03, 0x6a, 0x40, 0x4e, 0xc8, 0x6b, 0x4e, 0xb2, 0xba,
0xdc, 0xf4, 0xe8, 0x30, 0x9f, 0x8c, 0x0e, 0x6f, 0x41, 0xc3, 0xa4, 0x7e, 0x48, 0x97, 0x9f, 0x0a,
0x55, 0x20, 0x15, 0xad, 0xce, 0x7a, 0x39, 0x8b, 0xa0, 0x6b, 0x50, 0xb5, 0xc6, 0xc3, 0xae, 0x7d,
0xd0, 0x75, 0xec, 0x13, 0x97, 0x87, 0x99, 0x15, 0x6b, 0x3c, 0xfc, 0xce, 0x81, 0x66, 0x9f, 0xb8,
0x41, 0x24, 0x53, 0x3a, 0x63, 0x24, 0x73, 0x0d, 0xaa, 0x43, 0xfd, 0x05, 0xc1, 0xda, 0xb5, 0xc6,
0x43, 0x1a, 0x81, 0xe6, 0xb5, 0xca, 0x50, 0x7f, 0xa1, 0xd9, 0x27, 0xdb, 0xe3, 0x21, 0xba, 0x0d,
0xcd, 0x81, 0xee, 0x7a, 0xdd, 0x70, 0x08, 0x5b, 0xa6, 0x21, 0x6c, 0x83, 0xf4, 0x3f, 0x0e, 0xc2,
0xd8, 0x64, 0x4c, 0x54, 0x99, 0x23, 0x26, 0x32, 0x86, 0x83, 0x00, 0x11, 0x64, 0x8f, 0x89, 0x8c,
0xe1, 0x40, 0xa0, 0x79, 0x00, 0x0b, 0xfb, 0xd4, 0xbb, 0x73, 0x5b, 0xd5, 0x54, 0xdd, 0xb1, 0x41,
0x1c, 0x3b, 0xe6, 0x04, 0x6a, 0x3e, 0x38, 0xfa, 0x16, 0x54, 0xa8, 0x51, 0xa5, 0x63, 0x6b, 0x99,
0xc6, 0x06, 0x03, 0xc8, 0x68, 0x03, 0x0f, 0x3c, 0x9d, 0x8e, 0xae, 0x67, 0x1b, 0x2d, 0x06, 0x10,
0x7d, 0xd5, 0x73, 0xb0, 0xee, 0x61, 0x63, 0xf5, 0x74, 0xcd, 0x1e, 0x8e, 0x74, 0xca, 0x4c, 0xad,
0x06, 0x0d, 0x4e, 0x64, 0x9f, 0xd0, 0xdb, 0xd0, 0xe8, 0x89, 0xd6, 0x86, 0x63, 0x0f, 0x5b, 0x8b,
0x54, 0x8e, 0x62, 0xbd, 0xe8, 0x2a, 0x80, 0xaf, 0xa9, 0x74, 0xaf, 0xd5, 0xa4, 0xa7, 0x58, 0xe1,
0x3d, 0x8f, 0x68, 0x86, 0xca, 0x74, 0xbb, 0x2c, 0x17, 0x64, 0x5a, 0xfd, 0xd6, 0x12, 0xa5, 0x58,
0xf5, 0x93, 0x47, 0xa6, 0xd5, 0x47, 0x17, 0x61, 0xc1, 0x74, 0xbb, 0x07, 0xfa, 0x11, 0x6e, 0x21,
0xfa, 0xb5, 0x64, 0xba, 0x1b, 0xfa, 0x11, 0x56, 0x7f, 0x04, 0x17, 0x02, 0xee, 0x0a, 0x9d, 0x64,
0x92, 0x29, 0x94, 0x59, 0x99, 0x62, 0xb2, 0x4f, 0xff, 0x55, 0x01, 0x96, 0x77, 0xf5, 0x63, 0xfc,
0xea, 0xc3, 0x87, 0x4c, 0x6a, 0x6d, 0x13, 0x96, 0x68, 0xc4, 0xb0, 0x12, 0x9a, 0xcf, 0x04, 0xbb,
0x1a, 0x66, 0x85, 0xe4, 0x40, 0xf4, 0x6d, 0xe2, 0x10, 0xe0, 0xde, 0xd1, 0x0e, 0x09, 0xc1, 0x7c,
0x9b, 0x7a, 0x55, 0x82, 0x67, 0x4d, 0x40, 0x69, 0xe1, 0x11, 0x68, 0x07, 0x16, 0xa3, 0xc7, 0xe0,
0x5b, 0xd3, 0x77, 0x26, 0xc6, 0xe7, 0xc1, 0xee, 0x6b, 0x8d, 0xc8, 0x61, 0xb8, 0xa8, 0x05, 0x0b,
0xdc, 0x14, 0x52, 0x9d, 0x51, 0xd6, 0xfc, 0x26, 0xda, 0x81, 0xf3, 0x6c, 0x05, 0xbb, 0x5c, 0x20,
0xd8, 0xe2, 0xcb, 0x99, 0x16, 0x2f, 0x1b, 0x1a, 0x95, 0xa7, 0xca, 0x59, 0xe5, 0xa9, 0x05, 0x0b,
0x9c, 0xc7, 0xa9, 0x1e, 0x29, 0x6b, 0x7e, 0x93, 0x1c, 0x73, 0xc0, 0xed, 0x55, 0xfa, 0x2d, 0xe8,
0x20, 0xa1, 0x17, 0x04, 0xfb, 0x39, 0x25, 0x93, 0xf4, 0x29, 0x94, 0x05, 0x87, 0x67, 0x0f, 0x81,
0xc5, 0x98, 0xb8, 0x7e, 0xcf, 0xc7, 0xf4, 0xbb, 0xfa, 0x8f, 0x0a, 0xd4, 0xd6, 0xc9, 0x92, 0x36,
0xed, 0x3e, 0xb5, 0x46, 0xb7, 0xa0, 0xe1, 0xe0, 0x9e, 0xed, 0x18, 0x5d, 0x6c, 0x79, 0x8e, 0x89,
0x59, 0x02, 0xa2, 0xa0, 0xd5, 0x59, 0xef, 0x63, 0xd6, 0x49, 0xc0, 0x88, 0xca, 0x76, 0x3d, 0x7d,
0x38, 0xea, 0x1e, 0x10, 0xd5, 0x90, 0x63, 0x60, 0xa2, 0x97, 0x6a, 0x86, 0x37, 0xa1, 0x16, 0x80,
0x79, 0x36, 0xa5, 0x5f, 0xd0, 0xaa, 0xa2, 0x6f, 0xcf, 0x46, 0x6f, 0x41, 0x83, 0xee, 0x69, 0x77,
0x60, 0xf7, 0xbb, 0x24, 0xa2, 0xe5, 0x86, 0xaa, 0x66, 0xf0, 0x69, 0x91, 0xb3, 0x8a, 0x42, 0xb9,
0xe6, 0x0f, 0x31, 0x37, 0x55, 0x02, 0x6a, 0xd7, 0xfc, 0x21, 0x56, 0xff, 0x41, 0x81, 0xfa, 0xba,
0xee, 0xe9, 0xdb, 0xb6, 0x81, 0xf7, 0x66, 0x34, 0xec, 0x19, 0xb2, 0xba, 0x57, 0xa0, 0x22, 0x56,
0xc0, 0x97, 0x14, 0x74, 0xa0, 0x0d, 0x68, 0xf8, 0xae, 0x65, 0x97, 0x45, 0x5c, 0x85, 0x54, 0x07,
0x2a, 0x64, 0x39, 0x5d, 0xad, 0xee, 0x0f, 0xa3, 0x4d, 0x75, 0x03, 0x6a, 0xe1, 0xcf, 0x84, 0xea,
0x6e, 0x9c, 0x51, 0x44, 0x07, 0xe1, 0xc6, 0xed, 0xf1, 0x90, 0x9c, 0x29, 0x57, 0x2c, 0x7e, 0x53,
0xfd, 0x2d, 0x05, 0xea, 0xdc, 0xdc, 0xef, 0x8a, 0xfb, 0x0f, 0xba, 0x34, 0x96, 0x67, 0xa1, 0xbf,
0xd1, 0x37, 0xa3, 0x29, 0xcb, 0xb7, 0xa4, 0x4a, 0x80, 0x22, 0xa1, 0x4e, 0x66, 0xc4, 0xd6, 0x67,
0x89, 0xf1, 0xbf, 0x20, 0x8c, 0xc6, 0x8f, 0x86, 0x32, 0x5a, 0x0b, 0x16, 0x74, 0xc3, 0x70, 0xb0,
0xeb, 0xf2, 0x79, 0xf8, 0x4d, 0xf2, 0xe5, 0x18, 0x3b, 0xae, 0xcf, 0xf2, 0x79, 0xcd, 0x6f, 0xa2,
0x6f, 0x41, 0x59, 0x78, 0xa5, 0x2c, 0x41, 0x75, 0x23, 0x7d, 0x9e, 0x3c, 0x22, 0x15, 0x23, 0xd4,
0xbf, 0xcd, 0x41, 0x83, 0x6f, 0xd8, 0x2a, 0xb7, 0xc7, 0x93, 0x85, 0x6f, 0x15, 0x6a, 0x07, 0x81,
0xec, 0x4f, 0x4a, 0xab, 0x85, 0x55, 0x44, 0x64, 0xcc, 0x34, 0x01, 0x8c, 0x7a, 0x04, 0x85, 0xb9,
0x3c, 0x82, 0xe2, 0x59, 0x35, 0x58, 0xd2, 0x47, 0x2c, 0x49, 0x7c, 0x44, 0xf5, 0xd7, 0xa1, 0x1a,
0x42, 0x40, 0x35, 0x34, 0x4b, 0x5a, 0xf1, 0x1d, 0xf3, 0x9b, 0xe8, 0xa3, 0xc0, 0x2f, 0x62, 0x5b,
0x75, 0x49, 0x32, 0x97, 0x98, 0x4b, 0xa4, 0xfe, 0xbd, 0x02, 0x25, 0x8e, 0xf9, 0x3a, 0x54, 0xb9,
0xd2, 0xa1, 0x3e, 0x23, 0xc3, 0x0e, 0xbc, 0x8b, 0x38, 0x8d, 0x2f, 0x4f, 0xeb, 0x5c, 0x82, 0x72,
0x4c, 0xdf, 0x2c, 0x70, 0xb3, 0xe0, 0x7f, 0x0a, 0x29, 0x19, 0xf2, 0x89, 0xe8, 0x17, 0x74, 0x01,
0x8a, 0x03, 0xbb, 0x2f, 0xee, 0xb7, 0x58, 0x43, 0xfd, 0x52, 0xa1, 0xd7, 0x11, 0x1a, 0xee, 0xd9,
0xc7, 0xd8, 0x39, 0x9d, 0x3f, 0x8f, 0xfb, 0x30, 0xc4, 0xe6, 0x19, 0x83, 0x2f, 0x31, 0x00, 0x3d,
0x0c, 0x0e, 0x21, 0x2f, 0xcb, 0xf4, 0x84, 0xf5, 0x0e, 0x67, 0xd2, 0xe0, 0x30, 0xfe, 0x40, 0xa1,
0x19, 0xe9, 0xe8, 0x52, 0x66, 0xf5, 0x76, 0x5e, 0x4a, 0x20, 0xa3, 0x7e, 0xa5, 0x40, 0x3b, 0x48,
0x25, 0xb9, 0xab, 0xa7, 0xf3, 0xde, 0xf7, 0xbc, 0x9c, 0xf8, 0xea, 0x97, 0xc5, 0x85, 0x04, 0x11,
0xda, 0x4c, 0x91, 0x91, 0x7f, 0x1d, 0x61, 0xd1, 0xac, 0x74, 0x72, 0x41, 0xf3, 0xb0, 0x4c, 0x1b,
0xca, 0x22, 0x9f, 0xc1, 0x2e, 0x25, 0x44, 0x9b, 0x48, 0xd8, 0xa5, 0x27, 0xd8, 0xdb, 0x88, 0xa6,
0x42, 0x5e, 0xf7, 0x06, 0x86, 0x2f, 0x4a, 0x0e, 0xf9, 0x45, 0x49, 0x21, 0x76, 0x51, 0xc2, 0xfb,
0xd5, 0x21, 0x65, 0x81, 0xc4, 0x02, 0x5e, 0xd5, 0x86, 0xfd, 0xb6, 0x02, 0x2d, 0x4e, 0x85, 0xd2,
0x24, 0x21, 0xd1, 0x00, 0x7b, 0xd8, 0xf8, 0xba, 0x53, 0x05, 0xff, 0xad, 0x40, 0x33, 0x6c, 0x75,
0xa9, 0xe1, 0xfc, 0x18, 0x8a, 0x34, 0xd3, 0xc2, 0x67, 0x30, 0x55, 0x35, 0x30, 0x68, 0xa2, 0xb6,
0xa9, 0xab, 0xbd, 0x27, 0x1c, 0x04, 0xde, 0x0c, 0x4c, 0x7f, 0xfe, 0xec, 0xa6, 0x9f, 0xbb, 0x42,
0xf6, 0x98, 0xe0, 0x65, 0x29, 0xca, 0xa0, 0x03, 0x7d, 0x02, 0x25, 0x56, 0x63, 0xc2, 0x2f, 0x0f,
0x6f, 0x45, 0x51, 0xf3, 0xfa, 0x93, 0x50, 0xde, 0x9f, 0x76, 0x68, 0x7c, 0x90, 0xfa, 0xab, 0xb0,
0x1c, 0x44, 0xa3, 0x8c, 0xec, 0xac, 0x4c, 0xab, 0xfe, 0x8b, 0x02, 0xe7, 0x77, 0x4f, 0xad, 0x5e,
0x9c, 0xfd, 0x97, 0xa1, 0x34, 0x1a, 0xe8, 0x41, 0xc6, 0x94, 0xb7, 0xa8, 0x1b, 0xc8, 0x68, 0x63,
0x83, 0xd8, 0x10, 0xb6, 0x67, 0x55, 0xd1, 0xb7, 0x67, 0x4f, 0x35, 0xed, 0xb7, 0x44, 0xf8, 0x8c,
0x0d, 0x66, 0xad, 0x58, 0x1a, 0xaa, 0x2e, 0x7a, 0xa9, 0xb5, 0xfa, 0x04, 0x80, 0x1a, 0xf4, 0xee,
0x59, 0x8c, 0x38, 0x1d, 0xb1, 0x49, 0x54, 0xf6, 0x2f, 0x72, 0xd0, 0x0a, 0xed, 0xd2, 0xd7, 0xed,
0xdf, 0xa4, 0x44, 0x65, 0xf9, 0x97, 0x14, 0x95, 0x15, 0xe6, 0xf7, 0x69, 0x8a, 0x32, 0x9f, 0xe6,
0xdf, 0x72, 0xd0, 0x08, 0x76, 0x6d, 0x67, 0xa0, 0x5b, 0xa9, 0x9c, 0xb0, 0x2b, 0xfc, 0xf9, 0xe8,
0x3e, 0xbd, 0x27, 0x93, 0x93, 0x94, 0x83, 0xd0, 0x62, 0x28, 0xd0, 0x55, 0x7a, 0xe8, 0x8e, 0xc7,
0x12, 0x5f, 0x3c, 0x86, 0x60, 0x02, 0x69, 0x0e, 0x31, 0xba, 0x0b, 0x88, 0x4b, 0x51, 0xd7, 0xb4,
0xba, 0x2e, 0xee, 0xd9, 0x96, 0xc1, 0xe4, 0xab, 0xa8, 0x35, 0xf9, 0x97, 0x8e, 0xb5, 0xcb, 0xfa,
0xd1, 0xc7, 0x50, 0xf0, 0x4e, 0x47, 0xcc, 0x5b, 0x69, 0x48, 0xed, 0x7d, 0x30, 0xaf, 0xbd, 0xd3,
0x11, 0xd6, 0x28, 0xb8, 0x5f, 0x84, 0xe4, 0x39, 0xfa, 0x31, 0x77, 0xfd, 0x0a, 0x5a, 0xa8, 0x87,
0x68, 0x0c, 0x7f, 0x0f, 0x17, 0x98, 0x8b, 0xc4, 0x9b, 0x8c, 0xb3, 0x7d, 0xa1, 0xed, 0x7a, 0xde,
0x80, 0xa6, 0xee, 0x28, 0x67, 0xfb, 0xbd, 0x7b, 0xde, 0x40, 0xfd, 0xe7, 0x1c, 0x34, 0x03, 0xca,
0x1a, 0x76, 0xc7, 0x83, 0x74, 0x81, 0x9b, 0x9c, 0x1b, 0x99, 0x26, 0x6b, 0xdf, 0x86, 0x2a, 0x3f,
0xf6, 0x33, 0xb0, 0x0d, 0xb0, 0x21, 0x9b, 0x13, 0xf8, 0xb8, 0xf8, 0x92, 0xf8, 0xb8, 0x34, 0x43,
0x76, 0x41, 0xbe, 0xf9, 0xea, 0x4f, 0x15, 0x78, 0x23, 0xa1, 0x16, 0x27, 0x6e, 0xed, 0xe4, 0xd8,
0x8e, 0xab, 0xcb, 0x38, 0x4a, 0xae, 0xe0, 0x1f, 0x42, 0xc9, 0xa1, 0xd8, 0xf9, 0x55, 0xd0, 0xcd,
0x89, 0xdc, 0xc5, 0x26, 0xa2, 0xf1, 0x21, 0xea, 0x1f, 0x2a, 0x70, 0x31, 0x39, 0xd5, 0x39, 0xac,
0xf6, 0x2a, 0x2c, 0x30, 0xd4, 0xbe, 0x10, 0xde, 0x9e, 0x2c, 0x84, 0xc1, 0xe6, 0x68, 0xfe, 0x40,
0x75, 0x17, 0x96, 0x7d, 0xe3, 0x1e, 0x6c, 0xfd, 0x16, 0xf6, 0xf4, 0x09, 0x91, 0xcd, 0x75, 0xa8,
0x32, 0x17, 0x99, 0x45, 0x0c, 0x2c, 0x27, 0x00, 0xfb, 0x22, 0x95, 0xa6, 0xfe, 0xa7, 0x02, 0x17,
0xa8, 0x75, 0x8c, 0xdf, 0xbd, 0x64, 0xb9, 0x97, 0x53, 0x45, 0xca, 0x61, 0x5b, 0x1f, 0xf2, 0x12,
0x97, 0x8a, 0x16, 0xe9, 0x43, 0x9d, 0x64, 0xa6, 0x4d, 0x1a, 0x01, 0x07, 0x17, 0xb9, 0x24, 0xda,
0xa6, 0xf7, 0xb8, 0xf1, 0x14, 0x5b, 0x60, 0x95, 0x0b, 0xb3, 0x58, 0xe5, 0x4d, 0x78, 0x23, 0xb6,
0xd2, 0x39, 0x4e, 0x54, 0xfd, 0x4b, 0x85, 0x1c, 0x47, 0xa4, 0x54, 0x68, 0x76, 0xcf, 0xf4, 0xaa,
0xb8, 0xf4, 0xe9, 0x9a, 0x46, 0x5c, 0x89, 0x18, 0xe8, 0x53, 0xa8, 0x58, 0xf8, 0xa4, 0x1b, 0x76,
0x76, 0x32, 0xb8, 0xed, 0x65, 0x0b, 0x9f, 0xd0, 0x5f, 0xea, 0x36, 0x5c, 0x4c, 0x4c, 0x75, 0x9e,
0xb5, 0xff, 0x9d, 0x02, 0x97, 0xd6, 0x1d, 0x7b, 0xf4, 0xb9, 0xe9, 0x78, 0x63, 0x7d, 0x10, 0xbd,
0x22, 0x7f, 0x35, 0xa9, 0xab, 0xcf, 0x42, 0x6e, 0x2f, 0xe3, 0x9f, 0xbb, 0x12, 0x09, 0x4a, 0x4e,
0x8a, 0x2f, 0x3a, 0xe4, 0x24, 0xff, 0x47, 0x5e, 0x36, 0x79, 0x0e, 0x37, 0xc5, 0xf1, 0xc8, 0x12,
0x41, 0x48, 0x33, 0xdd, 0xf9, 0x59, 0x33, 0xdd, 0x29, 0xea, 0xbd, 0xf0, 0x92, 0xd4, 0xfb, 0x99,
0x53, 0x2f, 0x9f, 0x41, 0xf4, 0x16, 0x82, 0x9a, 0xdf, 0x99, 0xae, 0x2f, 0x56, 0x01, 0x82, 0x8c,
0x3c, 0xaf, 0xf4, 0xcc, 0x82, 0x26, 0x34, 0x8a, 0x9c, 0x96, 0x30, 0xa5, 0xdc, 0x94, 0x87, 0x72,
0xc4, 0xdf, 0x85, 0xb6, 0x8c, 0x4b, 0xe7, 0xe1, 0xfc, 0x5f, 0xe4, 0x00, 0x3a, 0xa2, 0x38, 0x78,
0x36, 0x5b, 0x70, 0x13, 0x42, 0xee, 0x46, 0x20, 0xef, 0x61, 0x2e, 0x32, 0x88, 0x48, 0x88, 0xa0,
0x93, 0xc0, 0x24, 0x02, 0x51, 0x83, 0xe2, 0x09, 0x49, 0x0d, 0x63, 0x8a, 0xb8, 0xfa, 0xbd, 0x0c,
0x15, 0xc7, 0x3e, 0xe9, 0x12, 0x31, 0x33, 0xfc, 0xea, 0x67, 0xc7, 0x3e, 0x21, 0xc2, 0x67, 0xa0,
0x8b, 0xb0, 0xe0, 0xe9, 0xee, 0x11, 0xc1, 0x5f, 0x0a, 0x55, 0x69, 0x18, 0xe8, 0x02, 0x14, 0x0f,
0xcc, 0x01, 0x66, 0x45, 0x01, 0x15, 0x8d, 0x35, 0xd0, 0x37, 0xfc, 0x32, 0xbd, 0x72, 0xe6, 0x4a,
0x1c, 0x0a, 0xaf, 0x7e, 0xa9, 0xc0, 0x62, 0xb0, 0x6b, 0x54, 0x01, 0x11, 0x9d, 0x46, 0xf5, 0xd9,
0x9a, 0x6d, 0x30, 0x55, 0xd1, 0x48, 0xb1, 0x08, 0x6c, 0x20, 0xd3, 0x5a, 0xc1, 0x90, 0x49, 0x71,
0x30, 0x59, 0x17, 0x59, 0xb4, 0x69, 0xf8, 0x95, 0x29, 0x25, 0xc7, 0x3e, 0xe9, 0x18, 0x62, 0x37,
0x58, 0x69, 0x33, 0x8b, 0xfa, 0xc8, 0x6e, 0xac, 0xd1, 0xea, 0xe6, 0x9b, 0x50, 0xc7, 0x8e, 0x63,
0x3b, 0xdd, 0x21, 0x76, 0x5d, 0xbd, 0x8f, 0xb9, 0x03, 0x5e, 0xa3, 0x9d, 0x5b, 0xac, 0x4f, 0xfd,
0xe3, 0x02, 0x34, 0x82, 0xa5, 0xf8, 0xf7, 0xe0, 0xa6, 0xe1, 0xdf, 0x83, 0x9b, 0xe4, 0xe8, 0xc0,
0x61, 0xaa, 0x50, 0x1c, 0xee, 0x6a, 0xae, 0xa5, 0x68, 0x15, 0xde, 0xdb, 0x31, 0x88, 0x59, 0x26,
0x42, 0x66, 0xd9, 0x06, 0x0e, 0x0e, 0x17, 0xfc, 0x2e, 0x7e, 0xb6, 0x11, 0x1e, 0x29, 0x64, 0xe0,
0x91, 0x62, 0x06, 0x1e, 0x29, 0x49, 0x78, 0x64, 0x19, 0x4a, 0xfb, 0xe3, 0xde, 0x11, 0xf6, 0xb8,
0xc7, 0xc6, 0x5b, 0x51, 0xde, 0x29, 0xc7, 0x78, 0x47, 0xb0, 0x48, 0x25, 0xcc, 0x22, 0x97, 0xa1,
0xc2, 0x2e, 0x64, 0xbb, 0x9e, 0x4b, 0x6f, 0x97, 0xf2, 0x5a, 0x99, 0x75, 0xec, 0xb9, 0xe8, 0x81,
0xef, 0xce, 0x55, 0x65, 0xc2, 0x4e, 0xb5, 0x4e, 0x8c, 0x4b, 0x7c, 0x67, 0xee, 0x1d, 0x58, 0x0c,
0x6d, 0x07, 0xb5, 0x11, 0x35, 0x3a, 0xd5, 0x90, 0x3b, 0x4f, 0xcd, 0xc4, 0x2d, 0x68, 0x04, 0x5b,
0x42, 0xe1, 0xea, 0x2c, 0x8a, 0x12, 0xbd, 0x14, 0x4c, 0x70, 0x72, 0xe3, 0x6c, 0x9c, 0x8c, 0x2e,
0x41, 0x99, 0x87, 0x3f, 0x6e, 0x6b, 0x31, 0x92, 0x8d, 0x50, 0x7f, 0x00, 0x28, 0x98, 0xfd, 0x7c,
0xde, 0x62, 0x8c, 0x3d, 0x72, 0x71, 0xf6, 0x50, 0x7f, 0xa6, 0xc0, 0x52, 0x98, 0xd8, 0xac, 0x86,
0xf7, 0x53, 0xa8, 0xb2, 0xfb, 0xbd, 0x2e, 0x11, 0x7c, 0x9e, 0xe5, 0xb9, 0x3a, 0xf1, 0x5c, 0x34,
0x08, 0x1e, 0x47, 0x10, 0xf6, 0x3a, 0xb1, 0x9d, 0x23, 0xd3, 0xea, 0x77, 0xc9, 0xcc, 0x7c, 0x71,
0xab, 0xf1, 0xce, 0x6d, 0xd2, 0xa7, 0xfe, 0x58, 0x81, 0x6b, 0x4f, 0x47, 0x86, 0xee, 0xe1, 0x90,
0x07, 0x32, 0x6f, 0x51, 0xe2, 0xc7, 0x7e, 0x55, 0x60, 0x2e, 0xdb, 0x1d, 0x15, 0x83, 0x56, 0xff,
0x5a, 0xcc, 0x25, 0x51, 0xc9, 0x3b, 0xfb, 0x5c, 0xda, 0x50, 0x3e, 0xe6, 0xe8, 0xfc, 0xc7, 0x1e,
0x7e, 0x3b, 0x72, 0x0f, 0x9a, 0x3f, 0xfb, 0x3d, 0xa8, 0xba, 0x05, 0x97, 0x34, 0xec, 0x62, 0xcb,
0x88, 0xac, 0x66, 0xe6, 0x6c, 0xd2, 0x08, 0xda, 0x32, 0x74, 0xf3, 0x30, 0x2b, 0xf3, 0x5d, 0xbb,
0x0e, 0x41, 0xeb, 0x71, 0x55, 0x4c, 0x5c, 0x26, 0x4a, 0xc7, 0x53, 0xff, 0x2a, 0x07, 0x17, 0x1f,
0x19, 0x06, 0xd7, 0xe2, 0xdc, 0x1b, 0x7b, 0x55, 0x8e, 0x72, 0xdc, 0x91, 0xcc, 0x27, 0x1d, 0xc9,
0x97, 0xa5, 0x59, 0xb9, 0x8d, 0xb1, 0xc6, 0x43, 0xdf, 0x76, 0x3a, 0xac, 0x40, 0xe8, 0x21, 0xbf,
0x18, 0x23, 0x01, 0x3d, 0xb5, 0x9f, 0xd3, 0xfd, 0xab, 0xb2, 0x9f, 0x15, 0x53, 0x47, 0xd0, 0x4a,
0x6e, 0xd6, 0x9c, 0xaa, 0xc4, 0xdf, 0x91, 0x91, 0xcd, 0x32, 0xa8, 0x35, 0xe2, 0x42, 0xd1, 0xae,
0x1d, 0xdb, 0x55, 0xff, 0x2b, 0x07, 0xad, 0x5d, 0xfd, 0x18, 0xff, 0xff, 0x39, 0xa0, 0xef, 0xc1,
0x05, 0x57, 0x3f, 0xc6, 0xdd, 0x50, 0x60, 0xdc, 0x75, 0xf0, 0x73, 0xee, 0x82, 0xbe, 0x2b, 0xd3,
0x24, 0xd2, 0x3a, 0x1a, 0x6d, 0xc9, 0x8d, 0xf4, 0x6b, 0xf8, 0x39, 0x7a, 0x1b, 0x16, 0xc3, 0x85,
0x5a, 0x64, 0x6a, 0x65, 0xba, 0xe5, 0xf5, 0x50, 0x1d, 0x56, 0xc7, 0x50, 0x9f, 0xc3, 0x95, 0xa7,
0x96, 0x8b, 0xbd, 0x4e, 0x50, 0x4b, 0x34, 0x67, 0x08, 0x79, 0x1d, 0xaa, 0xc1, 0xc6, 0x27, 0x1e,
0x78, 0x18, 0xae, 0x6a, 0x43, 0x7b, 0x4b, 0x77, 0x8e, 0xfc, 0x3c, 0xf2, 0x3a, 0xab, 0xf9, 0x78,
0x85, 0x04, 0x0f, 0x44, 0x09, 0x94, 0x86, 0x0f, 0xb0, 0x83, 0xad, 0x1e, 0xde, 0xb4, 0x7b, 0x47,
0xa1, 0xd2, 0x60, 0x25, 0x5c, 0x1a, 0x3c, 0x6b, 0xa9, 0xb1, 0xfa, 0xf3, 0x1c, 0x2c, 0x3f, 0x1a,
0x78, 0xd8, 0x09, 0x22, 0xff, 0xb3, 0x24, 0x31, 0x82, 0xac, 0x42, 0x6e, 0x86, 0xac, 0x42, 0xa2,
0xca, 0x3d, 0x9f, 0xac, 0x72, 0x97, 0xe5, 0x40, 0x0a, 0x33, 0xe6, 0x40, 0x1e, 0x01, 0x8c, 0x1c,
0x7b, 0x84, 0x1d, 0xcf, 0xc4, 0x7e, 0xf8, 0x96, 0xc1, 0x7d, 0x09, 0x0d, 0xba, 0xf3, 0xa9, 0x28,
0xe3, 0xdc, 0x3b, 0x1d, 0x61, 0xb4, 0x00, 0xf9, 0x6d, 0x7c, 0xd2, 0x3c, 0x87, 0x00, 0x4a, 0xdb,
0xb6, 0x33, 0xd4, 0x07, 0x4d, 0x05, 0x55, 0x61, 0x81, 0xdf, 0x5a, 0x35, 0x73, 0xa8, 0x0e, 0x95,
0x35, 0x3f, 0xf3, 0xdf, 0xcc, 0xdf, 0xf9, 0x53, 0x05, 0x96, 0x12, 0xf7, 0x2a, 0xa8, 0x01, 0xf0,
0xd4, 0xea, 0xf1, 0x0b, 0xa7, 0xe6, 0x39, 0x54, 0x83, 0xb2, 0x7f, 0xfd, 0xc4, 0xf0, 0xed, 0xd9,
0x14, 0xba, 0x99, 0x43, 0x4d, 0xa8, 0xb1, 0x81, 0xe3, 0x5e, 0x0f, 0xbb, 0x6e, 0x33, 0x2f, 0x7a,
0x36, 0x74, 0x73, 0x30, 0x76, 0x70, 0xb3, 0x40, 0x68, 0xee, 0xd9, 0xbc, 0x90, 0xbd, 0x59, 0x44,
0x08, 0x1a, 0x7e, 0x55, 0x3b, 0x1f, 0x54, 0x0a, 0xf5, 0xf9, 0xc3, 0x16, 0xee, 0x3c, 0x0b, 0x67,
0xc7, 0xe9, 0xf2, 0x2e, 0xc2, 0xf9, 0xa7, 0x96, 0x81, 0x0f, 0x4c, 0x0b, 0x1b, 0xc1, 0xa7, 0xe6,
0x39, 0x74, 0x1e, 0x16, 0xb7, 0xb0, 0xd3, 0xc7, 0xa1, 0xce, 0x1c, 0x5a, 0x82, 0xfa, 0x96, 0xf9,
0x22, 0xd4, 0x95, 0x57, 0x0b, 0x65, 0xa5, 0xa9, 0xac, 0xfc, 0xce, 0x55, 0xa8, 0x90, 0x43, 0x59,
0xb3, 0x6d, 0xc7, 0x40, 0x03, 0x40, 0xf4, 0xdd, 0xc7, 0x70, 0x64, 0x5b, 0xe2, 0xa1, 0x18, 0xba,
0x17, 0x3d, 0x07, 0xde, 0x48, 0x02, 0x72, 0xee, 0x6c, 0xbf, 0x25, 0x85, 0x8f, 0x01, 0xab, 0xe7,
0xd0, 0x90, 0x52, 0xdb, 0x33, 0x87, 0x78, 0xcf, 0xec, 0x1d, 0xf9, 0x9e, 0xc5, 0x07, 0x29, 0x7e,
0x44, 0x12, 0xd4, 0xa7, 0x77, 0x53, 0x4a, 0x8f, 0x3d, 0xcc, 0xf1, 0xad, 0x8c, 0x7a, 0x0e, 0x3d,
0x87, 0x0b, 0x4f, 0x70, 0xc8, 0x49, 0xf3, 0x09, 0xae, 0xa4, 0x13, 0x4c, 0x00, 0x9f, 0x91, 0xe4,
0x26, 0x14, 0x29, 0xbb, 0x21, 0x99, 0x1f, 0x17, 0x7e, 0xd3, 0xdd, 0xbe, 0x91, 0x0e, 0x20, 0xb0,
0xfd, 0x00, 0x16, 0x63, 0x2f, 0x41, 0x91, 0x4c, 0xab, 0xcb, 0xdf, 0xf4, 0xb6, 0xef, 0x64, 0x01,
0x15, 0xb4, 0xfa, 0xd0, 0x88, 0xbe, 0x17, 0x41, 0xb7, 0x33, 0x3c, 0x3d, 0x63, 0x94, 0xde, 0xcd,
0xfc, 0x48, 0x8d, 0x32, 0x41, 0x33, 0xfe, 0x32, 0x11, 0xdd, 0x99, 0x88, 0x20, 0xca, 0x6c, 0xef,
0x65, 0x82, 0x15, 0xe4, 0x4e, 0x29, 0x13, 0x24, 0x5e, 0x84, 0xc5, 0x79, 0xdc, 0x47, 0x93, 0xf6,
0x54, 0xad, 0x7d, 0x3f, 0x33, 0xbc, 0x20, 0xfd, 0x9b, 0xac, 0x2c, 0x45, 0xf6, 0xaa, 0x0a, 0x7d,
0x28, 0x47, 0x37, 0xe1, 0x39, 0x58, 0x7b, 0xe5, 0x2c, 0x43, 0xc4, 0x24, 0x7e, 0x44, 0xeb, 0x49,
0x24, 0xef, 0x92, 0xe2, 0x72, 0xe7, 0xe3, 0x4b, 0x7f, 0x72, 0xd5, 0xfe, 0xf0, 0x0c, 0x23, 0xc4,
0x04, 0xec, 0xf8, 0xd3, 0x4f, 0x5f, 0x0c, 0xef, 0x4f, 0xe5, 0x9a, 0xd9, 0x64, 0xf0, 0xfb, 0xb0,
0x18, 0xf3, 0x73, 0x50, 0x76, 0x5f, 0xa8, 0x3d, 0xc9, 0x19, 0x65, 0x22, 0x19, 0x2b, 0xcf, 0x41,
0x29, 0xdc, 0x2f, 0x29, 0xe1, 0x69, 0xdf, 0xc9, 0x02, 0x2a, 0x16, 0xe2, 0x52, 0x75, 0x19, 0x2b,
0xba, 0x40, 0x77, 0xe5, 0x38, 0xe4, 0xc5, 0x25, 0xed, 0xf7, 0x33, 0x42, 0x0b, 0xa2, 0xc7, 0x70,
0x5e, 0x52, 0x1b, 0x83, 0xde, 0x9f, 0x78, 0x58, 0xf1, 0xa2, 0xa0, 0xf6, 0xbd, 0xac, 0xe0, 0x82,
0xee, 0x6f, 0x00, 0xda, 0x3d, 0xb4, 0x4f, 0xd6, 0x6c, 0xeb, 0xc0, 0xec, 0x8f, 0x1d, 0x9d, 0x79,
0x09, 0x69, 0xb6, 0x21, 0x09, 0x9a, 0xc2, 0xa3, 0x13, 0x47, 0x08, 0xe2, 0x5d, 0x80, 0x27, 0xd8,
0xdb, 0xc2, 0x9e, 0x43, 0x04, 0xe3, 0xed, 0x34, 0xf3, 0xc7, 0x01, 0x7c, 0x52, 0xef, 0x4c, 0x85,
0x0b, 0x99, 0xa2, 0xe6, 0x96, 0x6e, 0x8d, 0xf5, 0x41, 0xa8, 0xb8, 0xff, 0xae, 0x74, 0x78, 0x1c,
0x2c, 0xe5, 0x20, 0x53, 0xa1, 0x05, 0xc9, 0x13, 0x61, 0xda, 0x43, 0x57, 0x71, 0x93, 0x4d, 0x7b,
0xb2, 0xce, 0x23, 0xae, 0xf6, 0x26, 0xc0, 0x0b, 0xc2, 0x5f, 0x28, 0xb4, 0xbc, 0x2a, 0x06, 0xf0,
0xcc, 0xf4, 0x0e, 0x77, 0x06, 0xba, 0xe5, 0x66, 0x99, 0x02, 0x05, 0x3c, 0xc3, 0x14, 0x38, 0xbc,
0x98, 0x82, 0x01, 0xf5, 0xc8, 0x0d, 0x19, 0x92, 0x55, 0xc3, 0xcb, 0x6e, 0x0b, 0xdb, 0xb7, 0xa7,
0x03, 0x0a, 0x2a, 0x87, 0x50, 0xf7, 0x45, 0x89, 0x6d, 0xee, 0xbb, 0x69, 0x33, 0x0d, 0x60, 0x52,
0x34, 0x81, 0x1c, 0x34, 0xac, 0x09, 0x92, 0x17, 0x00, 0x28, 0xdb, 0xc5, 0xd1, 0x24, 0x4d, 0x90,
0x7e, 0xab, 0xc0, 0x54, 0x5d, 0xec, 0xb2, 0x4d, 0xae, 0x47, 0xa5, 0x77, 0x87, 0x52, 0x55, 0x97,
0x72, 0x77, 0xa7, 0x9e, 0x43, 0xcf, 0xa0, 0xc4, 0xff, 0xc8, 0xe4, 0xad, 0xc9, 0x49, 0x3b, 0x8e,
0xfd, 0xd6, 0x14, 0x28, 0x81, 0xf8, 0x08, 0x2e, 0xa6, 0xa4, 0xec, 0xa4, 0x26, 0x78, 0x72, 0x7a,
0x6f, 0x9a, 0x71, 0x10, 0xc4, 0x12, 0x39, 0xb9, 0x09, 0xc4, 0xd2, 0xf2, 0x77, 0xd3, 0x88, 0xe9,
0x80, 0x92, 0xef, 0x77, 0xa5, 0x3c, 0x91, 0xfa, 0xcc, 0x37, 0x03, 0x89, 0xe4, 0x13, 0x5c, 0x29,
0x89, 0xd4, 0x97, 0xba, 0xd3, 0x48, 0x74, 0x61, 0x29, 0x91, 0xb4, 0x41, 0xef, 0xa5, 0x98, 0x6b,
0x59, 0x6a, 0x67, 0x1a, 0x81, 0x3e, 0xbc, 0x21, 0x4d, 0x50, 0x48, 0xdd, 0x8f, 0x49, 0xa9, 0x8c,
0x69, 0x84, 0x7a, 0x70, 0x5e, 0x92, 0x96, 0x90, 0x1a, 0xce, 0xf4, 0xf4, 0xc5, 0x34, 0x22, 0x07,
0xd0, 0x5e, 0x75, 0x6c, 0xdd, 0xe8, 0xe9, 0xae, 0x47, 0x53, 0x05, 0x24, 0x16, 0xf4, 0xfd, 0x3f,
0x79, 0x70, 0x20, 0x4d, 0x28, 0x4c, 0xa3, 0xb3, 0x0f, 0x55, 0xca, 0x90, 0xec, 0x8f, 0x32, 0x90,
0xdc, 0xd2, 0x85, 0x20, 0x52, 0xd4, 0xa7, 0x0c, 0xd0, 0x17, 0xcd, 0x95, 0x2f, 0x2b, 0x50, 0xf6,
0x1f, 0x24, 0x7c, 0xcd, 0x81, 0xe8, 0x6b, 0x88, 0x0c, 0xbf, 0x0f, 0x8b, 0xb1, 0xc7, 0xc1, 0xd2,
0xe3, 0x92, 0x3f, 0x20, 0x9e, 0x76, 0x5c, 0xcf, 0xf8, 0xbf, 0x72, 0x09, 0x27, 0xf1, 0x9d, 0xb4,
0xe8, 0x32, 0xee, 0x1f, 0x4e, 0x41, 0xfc, 0x7f, 0xdb, 0x2b, 0xdb, 0x06, 0x08, 0xf9, 0x63, 0x93,
0xcb, 0xf6, 0x88, 0x8b, 0x31, 0x6d, 0xb7, 0x86, 0x52, 0x97, 0xeb, 0xdd, 0x2c, 0x15, 0x52, 0xe9,
0x46, 0x33, 0xdd, 0xd1, 0x7a, 0x0a, 0xb5, 0x70, 0x41, 0x2d, 0x92, 0xfe, 0x07, 0x54, 0xb2, 0xe2,
0x76, 0xda, 0x2a, 0xb6, 0xce, 0x68, 0x8b, 0xa7, 0xa0, 0x73, 0x89, 0x11, 0x89, 0xdf, 0xd4, 0xa4,
0x18, 0x91, 0x94, 0xfb, 0x21, 0xa9, 0xef, 0x92, 0x7e, 0xfd, 0xc3, 0x92, 0x0c, 0xf1, 0xeb, 0x07,
0x69, 0x92, 0x21, 0xe5, 0x42, 0x47, 0x9a, 0x64, 0x48, 0xbb, 0xcf, 0x50, 0xcf, 0xad, 0x7e, 0xf4,
0xbd, 0x0f, 0xfb, 0xa6, 0x77, 0x38, 0xde, 0x27, 0xab, 0xbf, 0xcf, 0x86, 0xbe, 0x6f, 0xda, 0xfc,
0xd7, 0x7d, 0x9f, 0xdd, 0xef, 0x53, 0x6c, 0xf7, 0x09, 0xb6, 0xd1, 0xfe, 0x7e, 0x89, 0xb6, 0x3e,
0xfa, 0x9f, 0x00, 0x00, 0x00, 0xff, 0xff, 0xf1, 0xf1, 0x32, 0x41, 0x57, 0x50, 0x00, 0x00,
0x56, 0xce, 0xfa, 0x75, 0xd5, 0xab, 0x4f, 0x57, 0x87, 0x3d, 0xed, 0x72, 0xf9, 0x3b, 0x69, 0x7b,
0xc6, 0xe3, 0xf1, 0xd8, 0x33, 0x1e, 0x46, 0x6b, 0xd6, 0x3b, 0xb3, 0xb8, 0xbb, 0xdd, 0x9e, 0x82,
0xee, 0xde, 0xde, 0xec, 0xf6, 0x18, 0xcd, 0x22, 0x95, 0xb2, 0x2b, 0xa3, 0xab, 0x73, 0xbb, 0x2a,
0xb3, 0x9c, 0x99, 0xd5, 0xed, 0x5e, 0x0e, 0x3b, 0x02, 0x09, 0x69, 0x11, 0x62, 0x11, 0x12, 0x02,
0x0e, 0x48, 0x88, 0xd3, 0xb2, 0x68, 0x11, 0xd2, 0x8a, 0x0b, 0x17, 0xae, 0x23, 0x38, 0x8c, 0x10,
0x12, 0x47, 0x24, 0x38, 0x00, 0x77, 0xae, 0x1c, 0x50, 0x7c, 0x32, 0xf2, 0x17, 0x59, 0x95, 0x5d,
0x65, 0x8f, 0x11, 0x7b, 0xab, 0x88, 0x7c, 0xf1, 0x5e, 0x7c, 0xde, 0x3f, 0x5e, 0x14, 0x34, 0x0d,
0xdd, 0xd3, 0xbb, 0x3d, 0xdb, 0x76, 0x8c, 0xbb, 0x23, 0xc7, 0xf6, 0x6c, 0xb4, 0x34, 0x34, 0x07,
0x47, 0x63, 0x97, 0xb5, 0xee, 0x92, 0xcf, 0xed, 0x5a, 0xcf, 0x1e, 0x0e, 0x6d, 0x8b, 0x75, 0xb5,
0x1b, 0xa6, 0xe5, 0x61, 0xc7, 0xd2, 0x07, 0xbc, 0x5d, 0x0b, 0x0f, 0x68, 0xd7, 0xdc, 0xde, 0x01,
0x1e, 0xea, 0xac, 0xa5, 0x2e, 0x40, 0xf1, 0xf1, 0x70, 0xe4, 0x9d, 0xa8, 0x7f, 0xa2, 0x40, 0x6d,
0x7d, 0x30, 0x76, 0x0f, 0x34, 0xfc, 0x7c, 0x8c, 0x5d, 0x0f, 0xbd, 0x0f, 0x85, 0x3d, 0xdd, 0xc5,
0x2d, 0xe5, 0x9a, 0x72, 0xab, 0x7a, 0xff, 0xd2, 0xdd, 0x08, 0x55, 0x4e, 0x6f, 0xd3, 0xed, 0xaf,
0xe8, 0x2e, 0xd6, 0x28, 0x24, 0x42, 0x50, 0x30, 0xf6, 0x3a, 0x6b, 0xad, 0xdc, 0x35, 0xe5, 0x56,
0x5e, 0xa3, 0xbf, 0xd1, 0x15, 0x00, 0x17, 0xf7, 0x87, 0xd8, 0xf2, 0x3a, 0x6b, 0x6e, 0x2b, 0x7f,
0x2d, 0x7f, 0x2b, 0xaf, 0x85, 0x7a, 0x90, 0x0a, 0xb5, 0x9e, 0x3d, 0x18, 0xe0, 0x9e, 0x67, 0xda,
0x56, 0x67, 0xad, 0x55, 0xa0, 0x63, 0x23, 0x7d, 0xea, 0x7f, 0x28, 0x50, 0xe7, 0x53, 0x73, 0x47,
0xb6, 0xe5, 0x62, 0xf4, 0x21, 0x94, 0x5c, 0x4f, 0xf7, 0xc6, 0x2e, 0x9f, 0xdd, 0x45, 0xe9, 0xec,
0x76, 0x28, 0x88, 0xc6, 0x41, 0xa5, 0xd3, 0x8b, 0x93, 0xcf, 0x27, 0xc9, 0xc7, 0x96, 0x50, 0x48,
0x2c, 0xe1, 0x16, 0x2c, 0xee, 0x93, 0xd9, 0xed, 0x04, 0x40, 0x45, 0x0a, 0x14, 0xef, 0x26, 0x98,
0x3c, 0x73, 0x88, 0xbf, 0xb3, 0xbf, 0x83, 0xf5, 0x41, 0xab, 0x44, 0x69, 0x85, 0x7a, 0xd4, 0x7f,
0x52, 0xa0, 0x29, 0xc0, 0xfd, 0x73, 0x38, 0x07, 0xc5, 0x9e, 0x3d, 0xb6, 0x3c, 0xba, 0xd4, 0xba,
0xc6, 0x1a, 0xe8, 0x4d, 0xa8, 0xf5, 0x0e, 0x74, 0xcb, 0xc2, 0x83, 0xae, 0xa5, 0x0f, 0x31, 0x5d,
0x54, 0x45, 0xab, 0xf2, 0xbe, 0x2d, 0x7d, 0x88, 0x33, 0xad, 0xed, 0x1a, 0x54, 0x47, 0xba, 0xe3,
0x99, 0x91, 0xdd, 0x0f, 0x77, 0xa1, 0x36, 0x94, 0x4d, 0xb7, 0x33, 0x1c, 0xd9, 0x8e, 0xd7, 0x2a,
0x5e, 0x53, 0x6e, 0x95, 0x35, 0xd1, 0x26, 0x14, 0x4c, 0xfa, 0x6b, 0x57, 0x77, 0x0f, 0x3b, 0x6b,
0x7c, 0x45, 0x91, 0x3e, 0xf5, 0xcf, 0x15, 0x58, 0x7e, 0xe4, 0xba, 0x66, 0xdf, 0x4a, 0xac, 0x6c,
0x19, 0x4a, 0x96, 0x6d, 0xe0, 0xce, 0x1a, 0x5d, 0x5a, 0x5e, 0xe3, 0x2d, 0x74, 0x11, 0x2a, 0x23,
0x8c, 0x9d, 0xae, 0x63, 0x0f, 0xfc, 0x85, 0x95, 0x49, 0x87, 0x66, 0x0f, 0x30, 0xfa, 0x2e, 0x2c,
0xb9, 0x31, 0x44, 0x8c, 0xaf, 0xaa, 0xf7, 0xaf, 0xdf, 0x4d, 0x48, 0xc6, 0xdd, 0x38, 0x51, 0x2d,
0x39, 0x5a, 0xfd, 0x22, 0x07, 0x67, 0x05, 0x1c, 0x9b, 0x2b, 0xf9, 0x4d, 0x76, 0xde, 0xc5, 0x7d,
0x31, 0x3d, 0xd6, 0xc8, 0xb2, 0xf3, 0xe2, 0xc8, 0xf2, 0xe1, 0x23, 0xcb, 0xc0, 0xea, 0xf1, 0xf3,
0x28, 0x26, 0xcf, 0xe3, 0x2a, 0x54, 0xf1, 0x8b, 0x91, 0xe9, 0xe0, 0x2e, 0x61, 0x1c, 0xba, 0xe5,
0x05, 0x0d, 0x58, 0xd7, 0xae, 0x39, 0x0c, 0xcb, 0xc6, 0x42, 0x66, 0xd9, 0x50, 0xff, 0x42, 0x81,
0xf3, 0x89, 0x53, 0xe2, 0xc2, 0xa6, 0x41, 0x93, 0xae, 0x3c, 0xd8, 0x19, 0x22, 0x76, 0x64, 0xc3,
0xdf, 0x9a, 0xb4, 0xe1, 0x01, 0xb8, 0x96, 0x18, 0x1f, 0x9a, 0x64, 0x2e, 0xfb, 0x24, 0x0f, 0xe1,
0xfc, 0x13, 0xec, 0x71, 0x02, 0xe4, 0x1b, 0x76, 0x67, 0x57, 0x56, 0x51, 0xa9, 0xce, 0xc5, 0xa5,
0x5a, 0xfd, 0x9b, 0x9c, 0x90, 0x45, 0x4a, 0xaa, 0x63, 0xed, 0xdb, 0xe8, 0x12, 0x54, 0x04, 0x08,
0xe7, 0x8a, 0xa0, 0x03, 0x7d, 0x03, 0x8a, 0x64, 0xa6, 0x8c, 0x25, 0x1a, 0xf7, 0xdf, 0x94, 0xaf,
0x29, 0x84, 0x53, 0x63, 0xf0, 0xa8, 0x03, 0x0d, 0xd7, 0xd3, 0x1d, 0xaf, 0x3b, 0xb2, 0x5d, 0x7a,
0xce, 0x94, 0x71, 0xaa, 0xf7, 0xd5, 0x28, 0x06, 0xa1, 0xd6, 0x37, 0xdd, 0xfe, 0x36, 0x87, 0xd4,
0xea, 0x74, 0xa4, 0xdf, 0x44, 0x8f, 0xa1, 0x86, 0x2d, 0x23, 0x40, 0x54, 0xc8, 0x8c, 0xa8, 0x8a,
0x2d, 0x43, 0xa0, 0x09, 0xce, 0xa7, 0x98, 0xfd, 0x7c, 0x7e, 0x4f, 0x81, 0x56, 0xf2, 0x80, 0xe6,
0x51, 0xd9, 0x0f, 0xd9, 0x20, 0xcc, 0x0e, 0x68, 0xa2, 0x84, 0x8b, 0x43, 0xd2, 0xf8, 0x10, 0xf5,
0x8f, 0x14, 0x78, 0x23, 0x98, 0x0e, 0xfd, 0xf4, 0xaa, 0xb8, 0x05, 0xdd, 0x86, 0xa6, 0x69, 0xf5,
0x06, 0x63, 0x03, 0x3f, 0xb5, 0x3e, 0xc5, 0xfa, 0xc0, 0x3b, 0x38, 0xa1, 0x67, 0x58, 0xd6, 0x12,
0xfd, 0xea, 0xbf, 0xe6, 0x60, 0x39, 0x3e, 0xaf, 0x79, 0x36, 0xe9, 0x97, 0xa0, 0x68, 0x5a, 0xfb,
0xb6, 0xbf, 0x47, 0x57, 0x26, 0x08, 0x25, 0xa1, 0xc5, 0x80, 0x91, 0x0d, 0xc8, 0x57, 0x63, 0xbd,
0x03, 0xdc, 0x3b, 0x1c, 0xd9, 0x26, 0x55, 0x58, 0x04, 0xc5, 0xaf, 0x48, 0x50, 0xc8, 0x67, 0x7c,
0x77, 0x95, 0xe1, 0x58, 0x15, 0x28, 0x1e, 0x5b, 0x9e, 0x73, 0xa2, 0x2d, 0xf5, 0xe2, 0xfd, 0xed,
0x03, 0x58, 0x96, 0x03, 0xa3, 0x26, 0xe4, 0x0f, 0xf1, 0x09, 0x5d, 0x72, 0x45, 0x23, 0x3f, 0xd1,
0x03, 0x28, 0x1e, 0xe9, 0x83, 0x31, 0xe6, 0xda, 0x21, 0x0b, 0xfb, 0xb2, 0x01, 0xdf, 0xcc, 0x3d,
0x50, 0xd4, 0x21, 0x5c, 0x7c, 0x82, 0xbd, 0x8e, 0xe5, 0x62, 0xc7, 0x5b, 0x31, 0xad, 0x81, 0xdd,
0xdf, 0xd6, 0xbd, 0x83, 0x39, 0x74, 0x45, 0x44, 0xec, 0x73, 0x31, 0xb1, 0x57, 0x7f, 0xa2, 0xc0,
0x25, 0x39, 0x3d, 0x7e, 0xaa, 0x6d, 0x28, 0xef, 0x9b, 0x78, 0x60, 0x10, 0xd6, 0x51, 0x28, 0xeb,
0x88, 0x36, 0xd1, 0x19, 0x23, 0x02, 0xcc, 0x0f, 0xef, 0xcd, 0x94, 0x95, 0xee, 0x78, 0x8e, 0x69,
0xf5, 0x37, 0x4c, 0xd7, 0xd3, 0x18, 0x7c, 0x88, 0x55, 0xf2, 0xd9, 0x25, 0xf4, 0x77, 0x15, 0xb8,
0xf2, 0x04, 0x7b, 0xab, 0xc2, 0xe4, 0x90, 0xef, 0xa6, 0xeb, 0x99, 0x3d, 0xf7, 0xe5, 0xba, 0x7d,
0x19, 0x7c, 0x0f, 0xf5, 0xc7, 0x0a, 0x5c, 0x4d, 0x9d, 0x0c, 0xdf, 0x3a, 0xae, 0x52, 0x7d, 0x83,
0x23, 0x57, 0xa9, 0xbf, 0x86, 0x4f, 0x3e, 0x23, 0x87, 0xbf, 0xad, 0x9b, 0x0e, 0x53, 0xa9, 0x33,
0x1a, 0x98, 0x9f, 0x29, 0x70, 0xf9, 0x09, 0xf6, 0xb6, 0x7d, 0x73, 0xfb, 0x1a, 0x77, 0x87, 0xc0,
0x84, 0xcc, 0xbe, 0xef, 0x77, 0x46, 0xfa, 0xd4, 0xdf, 0x67, 0xc7, 0x29, 0x9d, 0xef, 0x6b, 0xd9,
0xc0, 0x2b, 0x54, 0x12, 0x42, 0x7a, 0x82, 0x4b, 0x3c, 0xdf, 0x3e, 0xf5, 0xcf, 0x14, 0xb8, 0xf0,
0xa8, 0xf7, 0x7c, 0x6c, 0x3a, 0x98, 0x03, 0x6d, 0xd8, 0xbd, 0xc3, 0xd9, 0x37, 0x37, 0xf0, 0x20,
0x73, 0x11, 0x0f, 0x72, 0x5a, 0xd4, 0xb1, 0x0c, 0x25, 0x8f, 0xb9, 0xac, 0xcc, 0x09, 0xe3, 0x2d,
0x3a, 0x3f, 0x0d, 0x0f, 0xb0, 0xee, 0xfe, 0xdf, 0x9c, 0xdf, 0x8f, 0x0b, 0x50, 0xfb, 0x8c, 0xab,
0x56, 0xea, 0x90, 0xc4, 0x39, 0x49, 0x91, 0xfb, 0x94, 0x21, 0xe7, 0x54, 0xe6, 0xaf, 0x3e, 0x81,
0xba, 0x8b, 0xf1, 0xe1, 0x2c, 0xee, 0x47, 0x8d, 0x0c, 0x14, 0x6e, 0xc3, 0x06, 0x2c, 0x8d, 0x2d,
0x1a, 0xf5, 0x60, 0x83, 0x6f, 0x20, 0xe3, 0xdc, 0xe9, 0x66, 0x29, 0x39, 0x10, 0x7d, 0xca, 0x03,
0xab, 0x10, 0xae, 0x62, 0x26, 0x5c, 0xf1, 0x61, 0xa8, 0x03, 0x4d, 0xc3, 0xb1, 0x47, 0x23, 0x6c,
0x74, 0x5d, 0x1f, 0x55, 0x29, 0x1b, 0x2a, 0x3e, 0x4e, 0xa0, 0x7a, 0x1f, 0xce, 0xc6, 0x67, 0xda,
0x31, 0x88, 0xaf, 0x4d, 0xce, 0x50, 0xf6, 0x09, 0xdd, 0x81, 0xa5, 0x24, 0x7c, 0x99, 0xc2, 0x27,
0x3f, 0xa0, 0xf7, 0x00, 0xc5, 0xa6, 0x4a, 0xc0, 0x2b, 0x0c, 0x3c, 0x3a, 0x99, 0x8e, 0xe1, 0xaa,
0x3f, 0x52, 0x60, 0xf9, 0x99, 0xee, 0xf5, 0x0e, 0xd6, 0x86, 0x5c, 0xd6, 0xe6, 0xd0, 0x55, 0x1f,
0x43, 0xe5, 0x88, 0xf3, 0x85, 0x6f, 0x90, 0xae, 0x4a, 0xf6, 0x27, 0xcc, 0x81, 0x5a, 0x30, 0x82,
0x84, 0x7a, 0xe7, 0xd6, 0x43, 0x21, 0xef, 0x6b, 0xd0, 0x9a, 0x53, 0x62, 0x75, 0xf5, 0x05, 0x00,
0x9f, 0xdc, 0xa6, 0xdb, 0x9f, 0x61, 0x5e, 0x0f, 0x60, 0x81, 0x63, 0xe3, 0x6a, 0x71, 0x1a, 0xff,
0xf8, 0xe0, 0xea, 0x4f, 0x4b, 0x50, 0x0d, 0x7d, 0x40, 0x0d, 0xc8, 0x09, 0x79, 0xcd, 0x49, 0x56,
0x97, 0x9b, 0x1e, 0x1d, 0xe6, 0x93, 0xd1, 0xe1, 0x4d, 0x68, 0x98, 0xd4, 0x0f, 0xe9, 0xf2, 0x53,
0xa1, 0x0a, 0xa4, 0xa2, 0xd5, 0x59, 0x2f, 0x67, 0x11, 0x74, 0x05, 0xaa, 0xd6, 0x78, 0xd8, 0xb5,
0xf7, 0xbb, 0x8e, 0x7d, 0xec, 0xf2, 0x30, 0xb3, 0x62, 0x8d, 0x87, 0xdf, 0xd9, 0xd7, 0xec, 0x63,
0x37, 0x88, 0x64, 0x4a, 0xa7, 0x8c, 0x64, 0xae, 0x40, 0x75, 0xa8, 0xbf, 0x20, 0x58, 0xbb, 0xd6,
0x78, 0x48, 0x23, 0xd0, 0xbc, 0x56, 0x19, 0xea, 0x2f, 0x34, 0xfb, 0x78, 0x6b, 0x3c, 0x44, 0xb7,
0xa0, 0x39, 0xd0, 0x5d, 0xaf, 0x1b, 0x0e, 0x61, 0xcb, 0x34, 0x84, 0x6d, 0x90, 0xfe, 0xc7, 0x41,
0x18, 0x9b, 0x8c, 0x89, 0x2a, 0x73, 0xc4, 0x44, 0xc6, 0x70, 0x10, 0x20, 0x82, 0xec, 0x31, 0x91,
0x31, 0x1c, 0x08, 0x34, 0x0f, 0x60, 0x61, 0x8f, 0x7a, 0x77, 0x6e, 0xab, 0x9a, 0xaa, 0x3b, 0xd6,
0x89, 0x63, 0xc7, 0x9c, 0x40, 0xcd, 0x07, 0x47, 0xdf, 0x82, 0x0a, 0x35, 0xaa, 0x74, 0x6c, 0x2d,
0xd3, 0xd8, 0x60, 0x00, 0x19, 0x6d, 0xe0, 0x81, 0xa7, 0xd3, 0xd1, 0xf5, 0x6c, 0xa3, 0xc5, 0x00,
0xa2, 0xaf, 0x7a, 0x0e, 0xd6, 0x3d, 0x6c, 0xac, 0x9c, 0xac, 0xda, 0xc3, 0x91, 0x4e, 0x99, 0xa9,
0xd5, 0xa0, 0xc1, 0x89, 0xec, 0x13, 0x7a, 0x0b, 0x1a, 0x3d, 0xd1, 0x5a, 0x77, 0xec, 0x61, 0x6b,
0x91, 0xca, 0x51, 0xac, 0x17, 0x5d, 0x06, 0xf0, 0x35, 0x95, 0xee, 0xb5, 0x9a, 0xf4, 0x14, 0x2b,
0xbc, 0xe7, 0x11, 0xcd, 0x50, 0x99, 0x6e, 0x97, 0xe5, 0x82, 0x4c, 0xab, 0xdf, 0x5a, 0xa2, 0x14,
0xab, 0x7e, 0xf2, 0xc8, 0xb4, 0xfa, 0xe8, 0x3c, 0x2c, 0x98, 0x6e, 0x77, 0x5f, 0x3f, 0xc4, 0x2d,
0x44, 0xbf, 0x96, 0x4c, 0x77, 0x5d, 0x3f, 0xc4, 0xea, 0x0f, 0xe1, 0x5c, 0xc0, 0x5d, 0xa1, 0x93,
0x4c, 0x32, 0x85, 0x32, 0x2b, 0x53, 0x4c, 0xf6, 0xe9, 0xbf, 0x2a, 0xc0, 0xf2, 0x8e, 0x7e, 0x84,
0x5f, 0x7d, 0xf8, 0x90, 0x49, 0xad, 0x6d, 0xc0, 0x12, 0x8d, 0x18, 0xee, 0x87, 0xe6, 0x33, 0xc1,
0xae, 0x86, 0x59, 0x21, 0x39, 0x10, 0x7d, 0x9b, 0x38, 0x04, 0xb8, 0x77, 0xb8, 0x4d, 0x42, 0x30,
0xdf, 0xa6, 0x5e, 0x96, 0xe0, 0x59, 0x15, 0x50, 0x5a, 0x78, 0x04, 0xda, 0x86, 0xc5, 0xe8, 0x31,
0xf8, 0xd6, 0xf4, 0xed, 0x89, 0xf1, 0x79, 0xb0, 0xfb, 0x5a, 0x23, 0x72, 0x18, 0x2e, 0x6a, 0xc1,
0x02, 0x37, 0x85, 0x54, 0x67, 0x94, 0x35, 0xbf, 0x89, 0xb6, 0xe1, 0x2c, 0x5b, 0xc1, 0x0e, 0x17,
0x08, 0xb6, 0xf8, 0x72, 0xa6, 0xc5, 0xcb, 0x86, 0x46, 0xe5, 0xa9, 0x72, 0x5a, 0x79, 0x6a, 0xc1,
0x02, 0xe7, 0x71, 0xaa, 0x47, 0xca, 0x9a, 0xdf, 0x24, 0xc7, 0x1c, 0x70, 0x7b, 0x95, 0x7e, 0x0b,
0x3a, 0x48, 0xe8, 0x05, 0xc1, 0x7e, 0x4e, 0xc9, 0x24, 0x7d, 0x02, 0x65, 0xc1, 0xe1, 0xd9, 0x43,
0x60, 0x31, 0x26, 0xae, 0xdf, 0xf3, 0x31, 0xfd, 0xae, 0xfe, 0xa3, 0x02, 0xb5, 0x35, 0xb2, 0xa4,
0x0d, 0xbb, 0x4f, 0xad, 0xd1, 0x4d, 0x68, 0x38, 0xb8, 0x67, 0x3b, 0x46, 0x17, 0x5b, 0x9e, 0x63,
0x62, 0x96, 0x80, 0x28, 0x68, 0x75, 0xd6, 0xfb, 0x98, 0x75, 0x12, 0x30, 0xa2, 0xb2, 0x5d, 0x4f,
0x1f, 0x8e, 0xba, 0xfb, 0x44, 0x35, 0xe4, 0x18, 0x98, 0xe8, 0xa5, 0x9a, 0xe1, 0x4d, 0xa8, 0x05,
0x60, 0x9e, 0x4d, 0xe9, 0x17, 0xb4, 0xaa, 0xe8, 0xdb, 0xb5, 0xd1, 0x0d, 0x68, 0xd0, 0x3d, 0xed,
0x0e, 0xec, 0x7e, 0x97, 0x44, 0xb4, 0xdc, 0x50, 0xd5, 0x0c, 0x3e, 0x2d, 0x72, 0x56, 0x51, 0x28,
0xd7, 0xfc, 0x01, 0xe6, 0xa6, 0x4a, 0x40, 0xed, 0x98, 0x3f, 0xc0, 0xea, 0x3f, 0x28, 0x50, 0x5f,
0xd3, 0x3d, 0x7d, 0xcb, 0x36, 0xf0, 0xee, 0x8c, 0x86, 0x3d, 0x43, 0x56, 0xf7, 0x12, 0x54, 0xc4,
0x0a, 0xf8, 0x92, 0x82, 0x0e, 0xb4, 0x0e, 0x0d, 0xdf, 0xb5, 0xec, 0xb2, 0x88, 0xab, 0x90, 0xea,
0x40, 0x85, 0x2c, 0xa7, 0xab, 0xd5, 0xfd, 0x61, 0xb4, 0xa9, 0xae, 0x43, 0x2d, 0xfc, 0x99, 0x50,
0xdd, 0x89, 0x33, 0x8a, 0xe8, 0x20, 0xdc, 0xb8, 0x35, 0x1e, 0x92, 0x33, 0xe5, 0x8a, 0xc5, 0x6f,
0xaa, 0xbf, 0xad, 0x40, 0x9d, 0x9b, 0xfb, 0x1d, 0x71, 0xff, 0x41, 0x97, 0xc6, 0xf2, 0x2c, 0xf4,
0x37, 0xfa, 0x66, 0x34, 0x65, 0x79, 0x43, 0xaa, 0x04, 0x28, 0x12, 0xea, 0x64, 0x46, 0x6c, 0x7d,
0x96, 0x18, 0xff, 0x0b, 0xc2, 0x68, 0xfc, 0x68, 0x28, 0xa3, 0xb5, 0x60, 0x41, 0x37, 0x0c, 0x07,
0xbb, 0x2e, 0x9f, 0x87, 0xdf, 0x24, 0x5f, 0x8e, 0xb0, 0xe3, 0xfa, 0x2c, 0x9f, 0xd7, 0xfc, 0x26,
0xfa, 0x16, 0x94, 0x85, 0x57, 0xca, 0x12, 0x54, 0xd7, 0xd2, 0xe7, 0xc9, 0x23, 0x52, 0x31, 0x42,
0xfd, 0xdb, 0x1c, 0x34, 0xf8, 0x86, 0xad, 0x70, 0x7b, 0x3c, 0x59, 0xf8, 0x56, 0xa0, 0xb6, 0x1f,
0xc8, 0xfe, 0xa4, 0xb4, 0x5a, 0x58, 0x45, 0x44, 0xc6, 0x4c, 0x13, 0xc0, 0xa8, 0x47, 0x50, 0x98,
0xcb, 0x23, 0x28, 0x9e, 0x56, 0x83, 0x25, 0x7d, 0xc4, 0x92, 0xc4, 0x47, 0x54, 0x7f, 0x03, 0xaa,
0x21, 0x04, 0x54, 0x43, 0xb3, 0xa4, 0x15, 0xdf, 0x31, 0xbf, 0x89, 0x3e, 0x0c, 0xfc, 0x22, 0xb6,
0x55, 0x17, 0x24, 0x73, 0x89, 0xb9, 0x44, 0xea, 0xdf, 0x2b, 0x50, 0xe2, 0x98, 0xaf, 0x42, 0x95,
0x2b, 0x1d, 0xea, 0x33, 0x32, 0xec, 0xc0, 0xbb, 0x88, 0xd3, 0xf8, 0xf2, 0xb4, 0xce, 0x05, 0x28,
0xc7, 0xf4, 0xcd, 0x02, 0x37, 0x0b, 0xfe, 0xa7, 0x90, 0x92, 0x21, 0x9f, 0x88, 0x7e, 0x41, 0xe7,
0xa0, 0x38, 0xb0, 0xfb, 0xe2, 0x7e, 0x8b, 0x35, 0xd4, 0x2f, 0x15, 0x7a, 0x1d, 0xa1, 0xe1, 0x9e,
0x7d, 0x84, 0x9d, 0x93, 0xf9, 0xf3, 0xb8, 0x0f, 0x43, 0x6c, 0x9e, 0x31, 0xf8, 0x12, 0x03, 0xd0,
0xc3, 0xe0, 0x10, 0xf2, 0xb2, 0x4c, 0x4f, 0x58, 0xef, 0x70, 0x26, 0x0d, 0x0e, 0xe3, 0x0f, 0x14,
0x9a, 0x91, 0x8e, 0x2e, 0x65, 0x56, 0x6f, 0xe7, 0xa5, 0x04, 0x32, 0xea, 0x57, 0x0a, 0xb4, 0x83,
0x54, 0x92, 0xbb, 0x72, 0x32, 0xef, 0x7d, 0xcf, 0xcb, 0x89, 0xaf, 0x7e, 0x59, 0x5c, 0x48, 0x10,
0xa1, 0xcd, 0x14, 0x19, 0xf9, 0xd7, 0x11, 0x16, 0xcd, 0x4a, 0x27, 0x17, 0x34, 0x0f, 0xcb, 0xb4,
0xa1, 0x2c, 0xf2, 0x19, 0xec, 0x52, 0x42, 0xb4, 0x89, 0x84, 0x5d, 0x78, 0x82, 0xbd, 0xf5, 0x68,
0x2a, 0xe4, 0x75, 0x6f, 0x60, 0xf8, 0xa2, 0xe4, 0x80, 0x5f, 0x94, 0x14, 0x62, 0x17, 0x25, 0xbc,
0x5f, 0x1d, 0x52, 0x16, 0x48, 0x2c, 0xe0, 0x55, 0x6d, 0xd8, 0xef, 0x28, 0xd0, 0xe2, 0x54, 0x28,
0x4d, 0x12, 0x12, 0x0d, 0xb0, 0x87, 0x8d, 0xaf, 0x3b, 0x55, 0xf0, 0x3f, 0x0a, 0x34, 0xc3, 0x56,
0x97, 0x1a, 0xce, 0x8f, 0xa0, 0x48, 0x33, 0x2d, 0x7c, 0x06, 0x53, 0x55, 0x03, 0x83, 0x26, 0x6a,
0x9b, 0xba, 0xda, 0xbb, 0xc2, 0x41, 0xe0, 0xcd, 0xc0, 0xf4, 0xe7, 0x4f, 0x6f, 0xfa, 0xb9, 0x2b,
0x64, 0x8f, 0x09, 0x5e, 0x96, 0xa2, 0x0c, 0x3a, 0xd0, 0xc7, 0x50, 0x62, 0x35, 0x26, 0xfc, 0xf2,
0xf0, 0x66, 0x14, 0x35, 0xaf, 0x3f, 0x09, 0xe5, 0xfd, 0x69, 0x87, 0xc6, 0x07, 0xa9, 0xbf, 0x0a,
0xcb, 0x41, 0x34, 0xca, 0xc8, 0xce, 0xca, 0xb4, 0xea, 0xbf, 0x28, 0x70, 0x76, 0xe7, 0xc4, 0xea,
0xc5, 0xd9, 0x7f, 0x19, 0x4a, 0xa3, 0x81, 0x1e, 0x64, 0x4c, 0x79, 0x8b, 0xba, 0x81, 0x8c, 0x36,
0x36, 0x88, 0x0d, 0x61, 0x7b, 0x56, 0x15, 0x7d, 0xbb, 0xf6, 0x54, 0xd3, 0x7e, 0x53, 0x84, 0xcf,
0xd8, 0x60, 0xd6, 0x8a, 0xa5, 0xa1, 0xea, 0xa2, 0x97, 0x5a, 0xab, 0x8f, 0x01, 0xa8, 0x41, 0xef,
0x9e, 0xc6, 0x88, 0xd3, 0x11, 0x1b, 0x44, 0x65, 0xff, 0x3c, 0x07, 0xad, 0xd0, 0x2e, 0x7d, 0xdd,
0xfe, 0x4d, 0x4a, 0x54, 0x96, 0x7f, 0x49, 0x51, 0x59, 0x61, 0x7e, 0x9f, 0xa6, 0x28, 0xf3, 0x69,
0xfe, 0x3d, 0x07, 0x8d, 0x60, 0xd7, 0xb6, 0x07, 0xba, 0x95, 0xca, 0x09, 0x3b, 0xc2, 0x9f, 0x8f,
0xee, 0xd3, 0xbb, 0x32, 0x39, 0x49, 0x39, 0x08, 0x2d, 0x86, 0x02, 0x5d, 0xa6, 0x87, 0xee, 0x78,
0x2c, 0xf1, 0xc5, 0x63, 0x08, 0x26, 0x90, 0xe6, 0x10, 0xa3, 0x3b, 0x80, 0xb8, 0x14, 0x75, 0x4d,
0xab, 0xeb, 0xe2, 0x9e, 0x6d, 0x19, 0x4c, 0xbe, 0x8a, 0x5a, 0x93, 0x7f, 0xe9, 0x58, 0x3b, 0xac,
0x1f, 0x7d, 0x04, 0x05, 0xef, 0x64, 0xc4, 0xbc, 0x95, 0x86, 0xd4, 0xde, 0x07, 0xf3, 0xda, 0x3d,
0x19, 0x61, 0x8d, 0x82, 0xfb, 0x45, 0x48, 0x9e, 0xa3, 0x1f, 0x71, 0xd7, 0xaf, 0xa0, 0x85, 0x7a,
0x88, 0xc6, 0xf0, 0xf7, 0x70, 0x81, 0xb9, 0x48, 0xbc, 0xc9, 0x38, 0xdb, 0x17, 0xda, 0xae, 0xe7,
0x0d, 0x68, 0xea, 0x8e, 0x72, 0xb6, 0xdf, 0xbb, 0xeb, 0x0d, 0xd4, 0x7f, 0xce, 0x41, 0x33, 0xa0,
0xac, 0x61, 0x77, 0x3c, 0x48, 0x17, 0xb8, 0xc9, 0xb9, 0x91, 0x69, 0xb2, 0xf6, 0x6d, 0xa8, 0xf2,
0x63, 0x3f, 0x05, 0xdb, 0x00, 0x1b, 0xb2, 0x31, 0x81, 0x8f, 0x8b, 0x2f, 0x89, 0x8f, 0x4b, 0x33,
0x64, 0x17, 0xe4, 0x9b, 0xaf, 0xfe, 0x44, 0x81, 0x37, 0x12, 0x6a, 0x71, 0xe2, 0xd6, 0x4e, 0x8e,
0xed, 0xb8, 0xba, 0x8c, 0xa3, 0xe4, 0x0a, 0xfe, 0x21, 0x94, 0x1c, 0x8a, 0x9d, 0x5f, 0x05, 0x5d,
0x9f, 0xc8, 0x5d, 0x6c, 0x22, 0x1a, 0x1f, 0xa2, 0xfe, 0xa1, 0x02, 0xe7, 0x93, 0x53, 0x9d, 0xc3,
0x6a, 0xaf, 0xc0, 0x02, 0x43, 0xed, 0x0b, 0xe1, 0xad, 0xc9, 0x42, 0x18, 0x6c, 0x8e, 0xe6, 0x0f,
0x54, 0x77, 0x60, 0xd9, 0x37, 0xee, 0xc1, 0xd6, 0x6f, 0x62, 0x4f, 0x9f, 0x10, 0xd9, 0x5c, 0x85,
0x2a, 0x73, 0x91, 0x59, 0xc4, 0xc0, 0x72, 0x02, 0xb0, 0x27, 0x52, 0x69, 0xea, 0x7f, 0x29, 0x70,
0x8e, 0x5a, 0xc7, 0xf8, 0xdd, 0x4b, 0x96, 0x7b, 0x39, 0x55, 0xa4, 0x1c, 0xb6, 0xf4, 0x21, 0x2f,
0x71, 0xa9, 0x68, 0x91, 0x3e, 0xd4, 0x49, 0x66, 0xda, 0xa4, 0x11, 0x70, 0x70, 0x91, 0x4b, 0xa2,
0x6d, 0x7a, 0x8f, 0x1b, 0x4f, 0xb1, 0x05, 0x56, 0xb9, 0x30, 0x8b, 0x55, 0xde, 0x80, 0x37, 0x62,
0x2b, 0x9d, 0xe3, 0x44, 0xd5, 0xbf, 0x54, 0xc8, 0x71, 0x44, 0x4a, 0x85, 0x66, 0xf7, 0x4c, 0x2f,
0x8b, 0x4b, 0x9f, 0xae, 0x69, 0xc4, 0x95, 0x88, 0x81, 0x3e, 0x81, 0x8a, 0x85, 0x8f, 0xbb, 0x61,
0x67, 0x27, 0x83, 0xdb, 0x5e, 0xb6, 0xf0, 0x31, 0xfd, 0xa5, 0x6e, 0xc1, 0xf9, 0xc4, 0x54, 0xe7,
0x59, 0xfb, 0xdf, 0x29, 0x70, 0x61, 0xcd, 0xb1, 0x47, 0x9f, 0x99, 0x8e, 0x37, 0xd6, 0x07, 0xd1,
0x2b, 0xf2, 0x57, 0x93, 0xba, 0xfa, 0x34, 0xe4, 0xf6, 0x32, 0xfe, 0xb9, 0x23, 0x91, 0xa0, 0xe4,
0xa4, 0xf8, 0xa2, 0x43, 0x4e, 0xf2, 0x7f, 0xe6, 0x65, 0x93, 0xe7, 0x70, 0x53, 0x1c, 0x8f, 0x2c,
0x11, 0x84, 0x34, 0xd3, 0x9d, 0x9f, 0x35, 0xd3, 0x9d, 0xa2, 0xde, 0x0b, 0x2f, 0x49, 0xbd, 0x9f,
0x3a, 0xf5, 0xf2, 0x29, 0x44, 0x6f, 0x21, 0xa8, 0xf9, 0x9d, 0xe9, 0xfa, 0x62, 0x05, 0x20, 0xc8,
0xc8, 0xf3, 0x4a, 0xcf, 0x2c, 0x68, 0x42, 0xa3, 0xc8, 0x69, 0x09, 0x53, 0xca, 0x4d, 0x79, 0x28,
0x47, 0xfc, 0x5d, 0x68, 0xcb, 0xb8, 0x74, 0x1e, 0xce, 0xff, 0x79, 0x0e, 0xa0, 0x23, 0x8a, 0x83,
0x67, 0xb3, 0x05, 0xd7, 0x21, 0xe4, 0x6e, 0x04, 0xf2, 0x1e, 0xe6, 0x22, 0x83, 0x88, 0x84, 0x08,
0x3a, 0x09, 0x4c, 0x22, 0x10, 0x35, 0x28, 0x9e, 0x90, 0xd4, 0x30, 0xa6, 0x88, 0xab, 0xdf, 0x8b,
0x50, 0x71, 0xec, 0xe3, 0x2e, 0x11, 0x33, 0xc3, 0xaf, 0x7e, 0x76, 0xec, 0x63, 0x22, 0x7c, 0x06,
0x3a, 0x0f, 0x0b, 0x9e, 0xee, 0x1e, 0x12, 0xfc, 0xa5, 0x50, 0x95, 0x86, 0x81, 0xce, 0x41, 0x71,
0xdf, 0x1c, 0x60, 0x56, 0x14, 0x50, 0xd1, 0x58, 0x03, 0x7d, 0xc3, 0x2f, 0xd3, 0x2b, 0x67, 0xae,
0xc4, 0xa1, 0xf0, 0xea, 0x97, 0x0a, 0x2c, 0x06, 0xbb, 0x46, 0x15, 0x10, 0xd1, 0x69, 0x54, 0x9f,
0xad, 0xda, 0x06, 0x53, 0x15, 0x8d, 0x14, 0x8b, 0xc0, 0x06, 0x32, 0xad, 0x15, 0x0c, 0x99, 0x14,
0x07, 0x93, 0x75, 0x91, 0x45, 0x9b, 0x86, 0x5f, 0x99, 0x52, 0x72, 0xec, 0xe3, 0x8e, 0x21, 0x76,
0x83, 0x95, 0x36, 0xb3, 0xa8, 0x8f, 0xec, 0xc6, 0x2a, 0xad, 0x6e, 0xbe, 0x0e, 0x75, 0xec, 0x38,
0xb6, 0xd3, 0x1d, 0x62, 0xd7, 0xd5, 0xfb, 0x98, 0x3b, 0xe0, 0x35, 0xda, 0xb9, 0xc9, 0xfa, 0xd4,
0x3f, 0x2e, 0x40, 0x23, 0x58, 0x8a, 0x7f, 0x0f, 0x6e, 0x1a, 0xfe, 0x3d, 0xb8, 0x49, 0x8e, 0x0e,
0x1c, 0xa6, 0x0a, 0xc5, 0xe1, 0xae, 0xe4, 0x5a, 0x8a, 0x56, 0xe1, 0xbd, 0x1d, 0x83, 0x98, 0x65,
0x22, 0x64, 0x96, 0x6d, 0xe0, 0xe0, 0x70, 0xc1, 0xef, 0xe2, 0x67, 0x1b, 0xe1, 0x91, 0x42, 0x06,
0x1e, 0x29, 0x66, 0xe0, 0x91, 0x92, 0x84, 0x47, 0x96, 0xa1, 0xb4, 0x37, 0xee, 0x1d, 0x62, 0x8f,
0x7b, 0x6c, 0xbc, 0x15, 0xe5, 0x9d, 0x72, 0x8c, 0x77, 0x04, 0x8b, 0x54, 0xc2, 0x2c, 0x72, 0x11,
0x2a, 0xec, 0x42, 0xb6, 0xeb, 0xb9, 0xf4, 0x76, 0x29, 0xaf, 0x95, 0x59, 0xc7, 0xae, 0x8b, 0x1e,
0xf8, 0xee, 0x5c, 0x55, 0x26, 0xec, 0x54, 0xeb, 0xc4, 0xb8, 0xc4, 0x77, 0xe6, 0xde, 0x86, 0xc5,
0xd0, 0x76, 0x50, 0x1b, 0x51, 0xa3, 0x53, 0x0d, 0xb9, 0xf3, 0xd4, 0x4c, 0xdc, 0x84, 0x46, 0xb0,
0x25, 0x14, 0xae, 0xce, 0xa2, 0x28, 0xd1, 0x4b, 0xc1, 0x04, 0x27, 0x37, 0x4e, 0xc7, 0xc9, 0xe8,
0x02, 0x94, 0x79, 0xf8, 0xe3, 0xb6, 0x16, 0x23, 0xd9, 0x08, 0xf5, 0xfb, 0x80, 0x82, 0xd9, 0xcf,
0xe7, 0x2d, 0xc6, 0xd8, 0x23, 0x17, 0x67, 0x0f, 0xf5, 0xa7, 0x0a, 0x2c, 0x85, 0x89, 0xcd, 0x6a,
0x78, 0x3f, 0x81, 0x2a, 0xbb, 0xdf, 0xeb, 0x12, 0xc1, 0xe7, 0x59, 0x9e, 0xcb, 0x13, 0xcf, 0x45,
0x83, 0xe0, 0x71, 0x04, 0x61, 0xaf, 0x63, 0xdb, 0x39, 0x34, 0xad, 0x7e, 0x97, 0xcc, 0xcc, 0x17,
0xb7, 0x1a, 0xef, 0xdc, 0x22, 0x7d, 0xea, 0x8f, 0x14, 0xb8, 0xf2, 0x74, 0x64, 0xe8, 0x1e, 0x0e,
0x79, 0x20, 0xf3, 0x16, 0x25, 0x7e, 0xe4, 0x57, 0x05, 0xe6, 0xb2, 0xdd, 0x51, 0x31, 0x68, 0xf5,
0xaf, 0xc5, 0x5c, 0x12, 0x95, 0xbc, 0xb3, 0xcf, 0xa5, 0x0d, 0xe5, 0x23, 0x8e, 0xce, 0x7f, 0xec,
0xe1, 0xb7, 0x23, 0xf7, 0xa0, 0xf9, 0xd3, 0xdf, 0x83, 0xaa, 0x9b, 0x70, 0x41, 0xc3, 0x2e, 0xb6,
0x8c, 0xc8, 0x6a, 0x66, 0xce, 0x26, 0x8d, 0xa0, 0x2d, 0x43, 0x37, 0x0f, 0xb3, 0x32, 0xdf, 0xb5,
0xeb, 0x10, 0xb4, 0x1e, 0x57, 0xc5, 0xc4, 0x65, 0xa2, 0x74, 0x3c, 0xf5, 0xaf, 0x72, 0x70, 0xfe,
0x91, 0x61, 0x70, 0x2d, 0xce, 0xbd, 0xb1, 0x57, 0xe5, 0x28, 0xc7, 0x1d, 0xc9, 0x7c, 0xd2, 0x91,
0x7c, 0x59, 0x9a, 0x95, 0xdb, 0x18, 0x6b, 0x3c, 0xf4, 0x6d, 0xa7, 0xc3, 0x0a, 0x84, 0x1e, 0xf2,
0x8b, 0x31, 0x12, 0xd0, 0x53, 0xfb, 0x39, 0xdd, 0xbf, 0x2a, 0xfb, 0x59, 0x31, 0x75, 0x04, 0xad,
0xe4, 0x66, 0xcd, 0xa9, 0x4a, 0xfc, 0x1d, 0x19, 0xd9, 0x2c, 0x83, 0x5a, 0x23, 0x2e, 0x14, 0xed,
0xda, 0xb6, 0x5d, 0xf5, 0xbf, 0x73, 0xd0, 0xda, 0xd1, 0x8f, 0xf0, 0x2f, 0xce, 0x01, 0x7d, 0x0e,
0xe7, 0x5c, 0xfd, 0x08, 0x77, 0x43, 0x81, 0x71, 0xd7, 0xc1, 0xcf, 0xb9, 0x0b, 0xfa, 0x8e, 0x4c,
0x93, 0x48, 0xeb, 0x68, 0xb4, 0x25, 0x37, 0xd2, 0xaf, 0xe1, 0xe7, 0xe8, 0x2d, 0x58, 0x0c, 0x17,
0x6a, 0x91, 0xa9, 0x95, 0xe9, 0x96, 0xd7, 0x43, 0x75, 0x58, 0x1d, 0x43, 0x7d, 0x0e, 0x97, 0x9e,
0x5a, 0x2e, 0xf6, 0x3a, 0x41, 0x2d, 0xd1, 0x9c, 0x21, 0xe4, 0x55, 0xa8, 0x06, 0x1b, 0x9f, 0x78,
0xe0, 0x61, 0xb8, 0xaa, 0x0d, 0xed, 0x4d, 0xdd, 0x39, 0xf4, 0xf3, 0xc8, 0x6b, 0xac, 0xe6, 0xe3,
0x15, 0x12, 0xdc, 0x17, 0x25, 0x50, 0x1a, 0xde, 0xc7, 0x0e, 0xb6, 0x7a, 0x78, 0xc3, 0xee, 0x1d,
0x86, 0x4a, 0x83, 0x95, 0x70, 0x69, 0xf0, 0xac, 0xa5, 0xc6, 0xea, 0xcf, 0x72, 0xb0, 0xfc, 0x68,
0xe0, 0x61, 0x27, 0x88, 0xfc, 0x4f, 0x93, 0xc4, 0x08, 0xb2, 0x0a, 0xb9, 0x19, 0xb2, 0x0a, 0x89,
0x2a, 0xf7, 0x7c, 0xb2, 0xca, 0x5d, 0x96, 0x03, 0x29, 0xcc, 0x98, 0x03, 0x79, 0x04, 0x30, 0x72,
0xec, 0x11, 0x76, 0x3c, 0x13, 0xfb, 0xe1, 0x5b, 0x06, 0xf7, 0x25, 0x34, 0x48, 0xfd, 0x1c, 0x9a,
0x4f, 0x7a, 0xab, 0xb6, 0xb5, 0x6f, 0x3a, 0x43, 0x7f, 0xa3, 0x12, 0x42, 0xa7, 0x64, 0x10, 0xba,
0x5c, 0x42, 0xe8, 0x54, 0x13, 0x96, 0x42, 0xb8, 0xe7, 0x54, 0x5c, 0xfd, 0x5e, 0x77, 0xdf, 0xb4,
0x4c, 0x5a, 0x53, 0x95, 0xa3, 0xee, 0x27, 0xf4, 0x7b, 0xeb, 0xbc, 0xe7, 0xf6, 0x27, 0xa2, 0x1a,
0x75, 0xf7, 0x64, 0x84, 0xd1, 0x02, 0xe4, 0xb7, 0xf0, 0x71, 0xf3, 0x0c, 0x02, 0x28, 0x6d, 0xd9,
0xce, 0x50, 0x1f, 0x34, 0x15, 0x54, 0x85, 0x05, 0x7e, 0xf9, 0xd6, 0xcc, 0xa1, 0x3a, 0x54, 0x56,
0xfd, 0x0b, 0x8c, 0x66, 0xfe, 0xf6, 0x9f, 0x2a, 0xb0, 0x94, 0xb8, 0x1e, 0x42, 0x0d, 0x80, 0xa7,
0x56, 0x8f, 0xdf, 0x9b, 0x35, 0xcf, 0xa0, 0x1a, 0x94, 0xfd, 0x5b, 0x34, 0x86, 0x6f, 0xd7, 0xa6,
0xd0, 0xcd, 0x1c, 0x6a, 0x42, 0x8d, 0x0d, 0x1c, 0xf7, 0x7a, 0xd8, 0x75, 0x9b, 0x79, 0xd1, 0xb3,
0xae, 0x9b, 0x83, 0xb1, 0x83, 0x9b, 0x05, 0x42, 0x73, 0xd7, 0xe6, 0xf5, 0xf8, 0xcd, 0x22, 0x42,
0xd0, 0xf0, 0x8b, 0xf3, 0xf9, 0xa0, 0x52, 0xa8, 0xcf, 0x1f, 0xb6, 0x70, 0xfb, 0x59, 0x38, 0xc9,
0x4f, 0x97, 0x77, 0x1e, 0xce, 0x3e, 0xb5, 0x0c, 0xbc, 0x6f, 0x5a, 0xd8, 0x08, 0x3e, 0x35, 0xcf,
0xa0, 0xb3, 0xb0, 0xb8, 0x89, 0x9d, 0x3e, 0x0e, 0x75, 0xe6, 0xd0, 0x12, 0xd4, 0x37, 0xcd, 0x17,
0xa1, 0xae, 0xbc, 0x5a, 0x28, 0x2b, 0x4d, 0xe5, 0xfe, 0xbf, 0x5d, 0x86, 0x0a, 0xe1, 0xad, 0x55,
0xdb, 0x76, 0x0c, 0x34, 0x00, 0x44, 0x9f, 0xaf, 0x0c, 0x47, 0xb6, 0x25, 0xde, 0xbb, 0xa1, 0xbb,
0xd1, 0xe3, 0xe1, 0x8d, 0x24, 0x20, 0xe7, 0x9d, 0xf6, 0x0d, 0x29, 0x7c, 0x0c, 0x58, 0x3d, 0x83,
0x86, 0x94, 0xda, 0xae, 0x39, 0xc4, 0xbb, 0x66, 0xef, 0xd0, 0x77, 0x90, 0xde, 0x4f, 0x71, 0x87,
0x92, 0xa0, 0x3e, 0xbd, 0xeb, 0x52, 0x7a, 0xec, 0x7d, 0x91, 0xcf, 0x73, 0xea, 0x19, 0xf4, 0x1c,
0xce, 0x3d, 0xc1, 0x21, 0x5f, 0xd3, 0x27, 0x78, 0x3f, 0x9d, 0x60, 0x02, 0xf8, 0x94, 0x24, 0x37,
0xa0, 0x48, 0xd9, 0x0d, 0xc9, 0xdc, 0xd1, 0xf0, 0xd3, 0xf4, 0xf6, 0xb5, 0x74, 0x00, 0x81, 0xed,
0xfb, 0xb0, 0x18, 0x7b, 0xd0, 0x8a, 0x64, 0xc6, 0x49, 0xfe, 0x34, 0xb9, 0x7d, 0x3b, 0x0b, 0xa8,
0xa0, 0xd5, 0x87, 0x46, 0xf4, 0xd9, 0x0b, 0xba, 0x95, 0xe1, 0x05, 0x1d, 0xa3, 0xf4, 0x4e, 0xe6,
0xb7, 0x76, 0x94, 0x09, 0x9a, 0xf1, 0x07, 0x96, 0xe8, 0xf6, 0x44, 0x04, 0x51, 0x66, 0x7b, 0x37,
0x13, 0xac, 0x20, 0x77, 0x42, 0x99, 0x20, 0xf1, 0xb0, 0x2d, 0xce, 0xe3, 0x3e, 0x9a, 0xb4, 0x17,
0x77, 0xed, 0x7b, 0x99, 0xe1, 0x05, 0xe9, 0xdf, 0x62, 0xd5, 0x35, 0xb2, 0xc7, 0x61, 0xe8, 0x03,
0x39, 0xba, 0x09, 0xaf, 0xda, 0xda, 0xf7, 0x4f, 0x33, 0x44, 0x4c, 0xe2, 0x87, 0xb4, 0x2c, 0x46,
0xf2, 0xbc, 0x2a, 0x2e, 0x77, 0x3e, 0xbe, 0xf4, 0x97, 0x63, 0xed, 0x0f, 0x4e, 0x31, 0x42, 0x4c,
0xc0, 0x8e, 0xbf, 0x60, 0xf5, 0xc5, 0xf0, 0xde, 0x54, 0xae, 0x99, 0x4d, 0x06, 0xbf, 0x07, 0x8b,
0x31, 0x77, 0x0d, 0x65, 0x77, 0xe9, 0xda, 0x93, 0x4c, 0x13, 0x13, 0xc9, 0x58, 0x95, 0x11, 0x4a,
0xe1, 0x7e, 0x49, 0x25, 0x52, 0xfb, 0x76, 0x16, 0x50, 0xb1, 0x10, 0x97, 0xaa, 0xcb, 0x58, 0xed,
0x08, 0xba, 0x23, 0xc7, 0x21, 0xaf, 0x91, 0x69, 0xbf, 0x97, 0x11, 0x5a, 0x10, 0x3d, 0x82, 0xb3,
0x92, 0x12, 0x1f, 0xf4, 0xde, 0xc4, 0xc3, 0x8a, 0xd7, 0x36, 0xb5, 0xef, 0x66, 0x05, 0x17, 0x74,
0x7f, 0x13, 0xd0, 0xce, 0x81, 0x7d, 0x4c, 0x3d, 0x87, 0xfe, 0xd8, 0xd1, 0x99, 0xb3, 0x93, 0x66,
0x1b, 0x92, 0xa0, 0x29, 0x3c, 0x3a, 0x71, 0x84, 0x20, 0xde, 0x05, 0x78, 0x82, 0xbd, 0x4d, 0xec,
0x39, 0x44, 0x30, 0xde, 0x4a, 0x33, 0x7f, 0x1c, 0xc0, 0x27, 0xf5, 0xf6, 0x54, 0xb8, 0x90, 0x29,
0x6a, 0x6e, 0xea, 0xd6, 0x58, 0x1f, 0x84, 0xde, 0x28, 0xdc, 0x91, 0x0e, 0x8f, 0x83, 0xa5, 0x1c,
0x64, 0x2a, 0xb4, 0x20, 0x79, 0x2c, 0x4c, 0x7b, 0xe8, 0x46, 0x71, 0xb2, 0x69, 0x4f, 0x96, 0xab,
0xc4, 0xd5, 0xde, 0x04, 0x78, 0x41, 0xf8, 0x0b, 0x85, 0x56, 0x89, 0xc5, 0x00, 0x9e, 0x99, 0xde,
0xc1, 0xf6, 0x40, 0xb7, 0xdc, 0x2c, 0x53, 0xa0, 0x80, 0xa7, 0x98, 0x02, 0x87, 0x17, 0x53, 0x30,
0xa0, 0x1e, 0xb9, 0xe8, 0x43, 0xb2, 0xa2, 0x7e, 0xd9, 0xa5, 0x67, 0xfb, 0xd6, 0x74, 0x40, 0x41,
0xe5, 0x00, 0xea, 0xbe, 0x28, 0xb1, 0xcd, 0x7d, 0x27, 0x6d, 0xa6, 0x01, 0x4c, 0x8a, 0x26, 0x90,
0x83, 0x86, 0x35, 0x41, 0xf2, 0x1e, 0x03, 0x65, 0xbb, 0xff, 0x9a, 0xa4, 0x09, 0xd2, 0x2f, 0x47,
0x98, 0xaa, 0x8b, 0xdd, 0x19, 0xca, 0xf5, 0xa8, 0xf4, 0x0a, 0x54, 0xaa, 0xea, 0x52, 0xae, 0x20,
0xd5, 0x33, 0xe8, 0x19, 0x94, 0xf8, 0xff, 0xb1, 0xdc, 0x98, 0x9c, 0x7b, 0xe4, 0xd8, 0x6f, 0x4e,
0x81, 0x12, 0x88, 0x0f, 0xe1, 0x7c, 0x4a, 0xe6, 0x51, 0x6a, 0x82, 0x27, 0x67, 0x29, 0xa7, 0x19,
0x07, 0x41, 0x2c, 0x91, 0x5a, 0x9c, 0x40, 0x2c, 0x2d, 0x0d, 0x39, 0x8d, 0x98, 0x0e, 0x28, 0xf9,
0x0c, 0x59, 0xca, 0x13, 0xa9, 0xaf, 0x95, 0x33, 0x90, 0x48, 0xbe, 0x24, 0x96, 0x92, 0x48, 0x7d,
0x70, 0x3c, 0x8d, 0x44, 0x17, 0x96, 0x12, 0xb9, 0x27, 0xf4, 0x6e, 0x8a, 0xb9, 0x96, 0x65, 0xa8,
0xa6, 0x11, 0xe8, 0xc3, 0x1b, 0xd2, 0x3c, 0x8b, 0xd4, 0xfd, 0x98, 0x94, 0x91, 0x99, 0x46, 0xa8,
0x07, 0x67, 0x25, 0xd9, 0x15, 0xa9, 0xe1, 0x4c, 0xcf, 0xc2, 0x4c, 0x23, 0xb2, 0x0f, 0xed, 0x15,
0xc7, 0xd6, 0x8d, 0x9e, 0xee, 0x7a, 0x34, 0xe3, 0x41, 0x62, 0x41, 0xdf, 0xff, 0x93, 0x07, 0x07,
0xd2, 0xbc, 0xc8, 0x34, 0x3a, 0x7b, 0x50, 0xa5, 0x0c, 0xc9, 0xfe, 0xef, 0x03, 0xc9, 0x2d, 0x5d,
0x08, 0x22, 0x45, 0x7d, 0xca, 0x00, 0x85, 0x68, 0xfe, 0x3a, 0x54, 0x44, 0xa6, 0x00, 0xc9, 0x8a,
0x73, 0xe2, 0x39, 0x8a, 0xf6, 0x8d, 0xc9, 0x40, 0x3e, 0xe6, 0xfb, 0x5f, 0x56, 0xa0, 0xec, 0xbf,
0xd8, 0xf8, 0x9a, 0x43, 0xdc, 0xd7, 0x10, 0x73, 0x7e, 0x0f, 0x16, 0x63, 0xaf, 0xa7, 0xa5, 0x8c,
0x20, 0x7f, 0x61, 0x3d, 0x8d, 0x11, 0x9e, 0xf1, 0xbf, 0x2d, 0x13, 0xee, 0xe7, 0xdb, 0x69, 0x71,
0x6b, 0xdc, 0xf3, 0x9c, 0x82, 0xf8, 0xff, 0xb7, 0xbf, 0xb7, 0x05, 0x10, 0xf2, 0xf4, 0x26, 0xd7,
0x35, 0x12, 0xe7, 0x65, 0xda, 0x6e, 0x0d, 0xa5, 0xce, 0xdc, 0x3b, 0x59, 0x4a, 0xc8, 0xd2, 0xcd,
0x71, 0xba, 0x0b, 0xf7, 0x14, 0x6a, 0xe1, 0x8a, 0x63, 0x24, 0xfd, 0x93, 0xac, 0x64, 0x49, 0xf2,
0xb4, 0x55, 0x6c, 0x9e, 0xd2, 0xca, 0x4f, 0x41, 0xe7, 0x12, 0xf3, 0x14, 0xbf, 0xca, 0x4a, 0x31,
0x4f, 0x29, 0x17, 0x68, 0x52, 0xaf, 0x28, 0xfd, 0x7e, 0x8c, 0xa5, 0x2f, 0xe2, 0xf7, 0x33, 0xd2,
0xf4, 0x45, 0xca, 0x8d, 0x97, 0x34, 0x7d, 0x91, 0x76, 0xe1, 0xa3, 0x9e, 0x59, 0xf9, 0xf0, 0xf3,
0x0f, 0xfa, 0xa6, 0x77, 0x30, 0xde, 0x23, 0xab, 0xbf, 0xc7, 0x86, 0xbe, 0x67, 0xda, 0xfc, 0xd7,
0x3d, 0x9f, 0xdd, 0xef, 0x51, 0x6c, 0xf7, 0x08, 0xb6, 0xd1, 0xde, 0x5e, 0x89, 0xb6, 0x3e, 0xfc,
0xdf, 0x00, 0x00, 0x00, 0xff, 0xff, 0x7e, 0xd5, 0x8e, 0x9e, 0x78, 0x51, 0x00, 0x00,
}
// Reference imports to suppress errors if they are not otherwise used.
@ -5299,6 +5399,7 @@ type DataCoordClient interface {
MarkSegmentsDropped(ctx context.Context, in *MarkSegmentsDroppedRequest, opts ...grpc.CallOption) (*commonpb.Status, error)
BroadcastAlteredCollection(ctx context.Context, in *AlterCollectionRequest, opts ...grpc.CallOption) (*commonpb.Status, error)
CheckHealth(ctx context.Context, in *milvuspb.CheckHealthRequest, opts ...grpc.CallOption) (*milvuspb.CheckHealthResponse, error)
GcConfirm(ctx context.Context, in *GcConfirmRequest, opts ...grpc.CallOption) (*GcConfirmResponse, error)
}
type dataCoordClient struct {
@ -5615,6 +5716,15 @@ func (c *dataCoordClient) CheckHealth(ctx context.Context, in *milvuspb.CheckHea
return out, nil
}
func (c *dataCoordClient) GcConfirm(ctx context.Context, in *GcConfirmRequest, opts ...grpc.CallOption) (*GcConfirmResponse, error) {
out := new(GcConfirmResponse)
err := c.cc.Invoke(ctx, "/milvus.proto.data.DataCoord/GcConfirm", in, out, opts...)
if err != nil {
return nil, err
}
return out, nil
}
// DataCoordServer is the server API for DataCoord service.
type DataCoordServer interface {
GetComponentStates(context.Context, *milvuspb.GetComponentStatesRequest) (*milvuspb.ComponentStates, error)
@ -5653,6 +5763,7 @@ type DataCoordServer interface {
MarkSegmentsDropped(context.Context, *MarkSegmentsDroppedRequest) (*commonpb.Status, error)
BroadcastAlteredCollection(context.Context, *AlterCollectionRequest) (*commonpb.Status, error)
CheckHealth(context.Context, *milvuspb.CheckHealthRequest) (*milvuspb.CheckHealthResponse, error)
GcConfirm(context.Context, *GcConfirmRequest) (*GcConfirmResponse, error)
}
// UnimplementedDataCoordServer can be embedded to have forward compatible implementations.
@ -5761,6 +5872,9 @@ func (*UnimplementedDataCoordServer) BroadcastAlteredCollection(ctx context.Cont
func (*UnimplementedDataCoordServer) CheckHealth(ctx context.Context, req *milvuspb.CheckHealthRequest) (*milvuspb.CheckHealthResponse, error) {
return nil, status.Errorf(codes.Unimplemented, "method CheckHealth not implemented")
}
func (*UnimplementedDataCoordServer) GcConfirm(ctx context.Context, req *GcConfirmRequest) (*GcConfirmResponse, error) {
return nil, status.Errorf(codes.Unimplemented, "method GcConfirm not implemented")
}
func RegisterDataCoordServer(s *grpc.Server, srv DataCoordServer) {
s.RegisterService(&_DataCoord_serviceDesc, srv)
@ -6378,6 +6492,24 @@ func _DataCoord_CheckHealth_Handler(srv interface{}, ctx context.Context, dec fu
return interceptor(ctx, in, info, handler)
}
func _DataCoord_GcConfirm_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(GcConfirmRequest)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(DataCoordServer).GcConfirm(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: "/milvus.proto.data.DataCoord/GcConfirm",
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(DataCoordServer).GcConfirm(ctx, req.(*GcConfirmRequest))
}
return interceptor(ctx, in, info, handler)
}
var _DataCoord_serviceDesc = grpc.ServiceDesc{
ServiceName: "milvus.proto.data.DataCoord",
HandlerType: (*DataCoordServer)(nil),
@ -6518,6 +6650,10 @@ var _DataCoord_serviceDesc = grpc.ServiceDesc{
MethodName: "CheckHealth",
Handler: _DataCoord_CheckHealth_Handler,
},
{
MethodName: "GcConfirm",
Handler: _DataCoord_GcConfirm_Handler,
},
},
Streams: []grpc.StreamDesc{},
Metadata: "data_coord.proto",

View File

@ -24,12 +24,15 @@ import (
"github.com/milvus-io/milvus-proto/go-api/milvuspb"
"github.com/milvus-io/milvus/internal/proto/datapb"
"github.com/milvus-io/milvus/internal/proto/internalpb"
"github.com/milvus-io/milvus/internal/types"
"github.com/milvus-io/milvus/internal/util/funcutil"
"github.com/milvus-io/milvus/internal/util/typeutil"
"github.com/milvus-io/milvus/internal/util/uniquegenerator"
)
type DataCoordMock struct {
types.DataCoord
nodeID typeutil.UniqueID
address string

View File

@ -45,6 +45,7 @@ type Broker interface {
UnsetIsImportingState(context.Context, *datapb.UnsetIsImportingStateRequest) (*commonpb.Status, error)
MarkSegmentsDropped(context.Context, *datapb.MarkSegmentsDroppedRequest) (*commonpb.Status, error)
GetSegmentStates(context.Context, *datapb.GetSegmentStatesRequest) (*datapb.GetSegmentStatesResponse, error)
GcConfirm(ctx context.Context, collectionID, partitionID UniqueID) bool
DropCollectionIndex(ctx context.Context, collID UniqueID, partIDs []UniqueID) error
GetSegmentIndexState(ctx context.Context, collID UniqueID, indexName string, segIDs []UniqueID) ([]*indexpb.SegmentIndexState, error)
@ -282,3 +283,15 @@ func (b *ServerBroker) DescribeIndex(ctx context.Context, colID UniqueID) (*inde
CollectionID: colID,
})
}
func (b *ServerBroker) GcConfirm(ctx context.Context, collectionID, partitionID UniqueID) bool {
req := &datapb.GcConfirmRequest{CollectionId: collectionID, PartitionId: partitionID}
resp, err := b.s.dataCoord.GcConfirm(ctx, req)
if err != nil {
return false
}
if resp.GetStatus().GetErrorCode() != commonpb.ErrorCode_Success {
return false
}
return resp.GetGcFinished()
}

View File

@ -5,15 +5,15 @@ import (
"errors"
"testing"
"github.com/milvus-io/milvus/internal/metastore/model"
"github.com/milvus-io/milvus-proto/go-api/milvuspb"
"github.com/milvus-io/milvus/internal/proto/indexpb"
"github.com/milvus-io/milvus/internal/proto/datapb"
"github.com/milvus-io/milvus-proto/go-api/commonpb"
"github.com/milvus-io/milvus/internal/proto/datapb"
"github.com/milvus-io/milvus-proto/go-api/milvuspb"
"github.com/milvus-io/milvus/internal/metastore/model"
"github.com/milvus-io/milvus/internal/mocks"
"github.com/milvus-io/milvus/internal/proto/indexpb"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/mock"
)
func TestServerBroker_ReleaseCollection(t *testing.T) {
@ -356,3 +356,42 @@ func TestServerBroker_BroadcastAlteredCollection(t *testing.T) {
assert.NoError(t, err)
})
}
func TestServerBroker_GcConfirm(t *testing.T) {
t.Run("invalid datacoord", func(t *testing.T) {
dc := mocks.NewDataCoord(t)
dc.On("GcConfirm",
mock.Anything, // context.Context
mock.Anything, // *datapb.GcConfirmRequest
).Return(nil, errors.New("error mock GcConfirm"))
c := newTestCore(withDataCoord(dc))
broker := newServerBroker(c)
assert.False(t, broker.GcConfirm(context.Background(), 100, 10000))
})
t.Run("non success", func(t *testing.T) {
dc := mocks.NewDataCoord(t)
dc.On("GcConfirm",
mock.Anything, // context.Context
mock.Anything, // *datapb.GcConfirmRequest
).Return(
&datapb.GcConfirmResponse{Status: failStatus(commonpb.ErrorCode_UnexpectedError, "error mock GcConfirm")},
nil)
c := newTestCore(withDataCoord(dc))
broker := newServerBroker(c)
assert.False(t, broker.GcConfirm(context.Background(), 100, 10000))
})
t.Run("normal case", func(t *testing.T) {
dc := mocks.NewDataCoord(t)
dc.On("GcConfirm",
mock.Anything, // context.Context
mock.Anything, // *datapb.GcConfirmRequest
).Return(
&datapb.GcConfirmResponse{Status: succStatus(), GcFinished: true},
nil)
c := newTestCore(withDataCoord(dc))
broker := newServerBroker(c)
assert.True(t, broker.GcConfirm(context.Background(), 100, 10000))
})
}

View File

@ -91,6 +91,7 @@ func (t *dropCollectionTask) Execute(ctx context.Context) error {
baseStep: baseStep{core: t.core},
pChannels: collMeta.PhysicalChannelNames,
})
redoTask.AddAsyncStep(newConfirmGCStep(t.core, collMeta.CollectionID, allPartition))
redoTask.AddAsyncStep(&deleteCollectionMetaStep{
baseStep: baseStep{core: t.core},
collectionID: collMeta.CollectionID,

View File

@ -4,6 +4,7 @@ import (
"context"
"errors"
"testing"
"time"
"github.com/milvus-io/milvus/internal/common"
@ -148,6 +149,9 @@ func Test_dropCollectionTask_Execute(t *testing.T) {
t.Run("normal case, redo", func(t *testing.T) {
defer cleanTestEnv()
confirmGCInterval = time.Millisecond
defer restoreConfirmGCInterval()
collectionName := funcutil.GenRandomStr()
shardNum := 2
@ -187,8 +191,12 @@ func Test_dropCollectionTask_Execute(t *testing.T) {
broker.DropCollectionIndexFunc = func(ctx context.Context, collID UniqueID, partIDs []UniqueID) error {
dropIndexCalled = true
dropIndexChan <- struct{}{}
time.Sleep(confirmGCInterval)
return nil
}
broker.GCConfirmFunc = func(ctx context.Context, collectionID, partitionID UniqueID) bool {
return true
}
gc := newMockGarbageCollector()
deleteCollectionCalled := false

View File

@ -85,6 +85,7 @@ func (t *dropPartitionTask) Execute(ctx context.Context) error {
CollectionID: t.collMeta.CollectionID,
},
})
redoTask.AddAsyncStep(newConfirmGCStep(t.core, t.collMeta.CollectionID, partID))
redoTask.AddAsyncStep(&removePartitionMetaStep{
baseStep: baseStep{core: t.core},
collectionID: t.collMeta.CollectionID,

View File

@ -3,6 +3,7 @@ package rootcoord
import (
"context"
"testing"
"time"
"github.com/milvus-io/milvus/internal/metastore/model"
"github.com/milvus-io/milvus/internal/proto/etcdpb"
@ -125,6 +126,9 @@ func Test_dropPartitionTask_Execute(t *testing.T) {
})
t.Run("normal case", func(t *testing.T) {
confirmGCInterval = time.Millisecond
defer restoreConfirmGCInterval()
collectionName := funcutil.GenRandomStr()
partitionName := funcutil.GenRandomStr()
coll := &model.Collection{Name: collectionName, Partitions: []*model.Partition{{PartitionName: partitionName}}}
@ -146,10 +150,23 @@ func Test_dropPartitionTask_Execute(t *testing.T) {
gc.GcPartitionDataFunc = func(ctx context.Context, pChannels []string, coll *model.Partition) (Timestamp, error) {
deletePartitionChan <- struct{}{}
deletePartitionCalled = true
time.Sleep(confirmGCInterval)
return 0, nil
}
core := newTestCore(withValidProxyManager(), withMeta(meta), withGarbageCollector(gc), withDropIndex())
broker := newMockBroker()
broker.GCConfirmFunc = func(ctx context.Context, collectionID, partitionID UniqueID) bool {
return true
}
broker.DropCollectionIndexFunc = func(ctx context.Context, collID UniqueID, partIDs []UniqueID) error {
return nil
}
core := newTestCore(
withValidProxyManager(),
withMeta(meta),
withGarbageCollector(gc),
withBroker(broker))
task := &dropPartitionTask{
baseTask: baseTask{core: core},

View File

@ -28,7 +28,6 @@ import (
"github.com/milvus-io/milvus/internal/common"
"github.com/milvus-io/milvus/internal/log"
"github.com/milvus-io/milvus/internal/metastore"
"github.com/milvus-io/milvus/internal/metastore/kv/rootcoord"
"github.com/milvus-io/milvus/internal/metastore/model"
"github.com/milvus-io/milvus/internal/metrics"
"github.com/milvus-io/milvus/internal/proto/internalpb"
@ -38,29 +37,6 @@ import (
"go.uber.org/zap"
)
const (
// TimestampPrefix prefix for timestamp
TimestampPrefix = rootcoord.ComponentPrefix + "/timestamp"
// CreateCollectionDDType name of DD type for create collection
CreateCollectionDDType = "CreateCollection"
// DropCollectionDDType name of DD type for drop collection
DropCollectionDDType = "DropCollection"
// CreatePartitionDDType name of DD type for create partition
CreatePartitionDDType = "CreatePartition"
// DropPartitionDDType name of DD type for drop partition
DropPartitionDDType = "DropPartition"
// DefaultIndexType name of default index type for scalar field
DefaultIndexType = "STL_SORT"
// DefaultStringIndexType name of default index type for varChar/string field
DefaultStringIndexType = "Trie"
)
//go:generate mockery --name=IMetaTable --outpkg=mockrootcoord
type IMetaTable interface {
AddCollection(ctx context.Context, coll *model.Collection) error

View File

@ -827,6 +827,8 @@ type mockBroker struct {
GetSegmentIndexStateFunc func(ctx context.Context, collID UniqueID, indexName string, segIDs []UniqueID) ([]*indexpb.SegmentIndexState, error)
BroadcastAlteredCollectionFunc func(ctx context.Context, req *milvuspb.AlterCollectionRequest) error
GCConfirmFunc func(ctx context.Context, collectionID, partitionID UniqueID) bool
}
func newMockBroker() *mockBroker {
@ -861,6 +863,10 @@ func (b mockBroker) BroadcastAlteredCollection(ctx context.Context, req *milvusp
return b.BroadcastAlteredCollectionFunc(ctx, req)
}
func (b mockBroker) GcConfirm(ctx context.Context, collectionID, partitionID UniqueID) bool {
return b.GCConfirmFunc(ctx, collectionID, partitionID)
}
func withBroker(b Broker) Opt {
return func(c *Core) {
c.broker = b

View File

@ -3,6 +3,7 @@ package rootcoord
import (
"context"
"fmt"
"time"
"github.com/milvus-io/milvus-proto/go-api/milvuspb"
@ -14,10 +15,10 @@ import (
type stepPriority int
const (
stepPriorityLow = iota
stepPriorityNormal
stepPriorityImportant
stepPriorityUrgent
stepPriorityLow = 0
stepPriorityNormal = 1
stepPriorityImportant = 10
stepPriorityUrgent = 1000
)
type nestedStep interface {
@ -374,3 +375,50 @@ func (b *BroadcastAlteredCollectionStep) Execute(ctx context.Context) ([]nestedS
func (b *BroadcastAlteredCollectionStep) Desc() string {
return fmt.Sprintf("broadcast altered collection, collectionID: %d", b.req.CollectionID)
}
var (
confirmGCInterval = time.Minute * 20
allPartition UniqueID = -1
)
type confirmGCStep struct {
baseStep
collectionID UniqueID
partitionID UniqueID
lastScheduledTime time.Time
}
func newConfirmGCStep(core *Core, collectionID, partitionID UniqueID) *confirmGCStep {
return &confirmGCStep{
baseStep: baseStep{core: core},
collectionID: collectionID,
partitionID: partitionID,
lastScheduledTime: time.Now(),
}
}
func (b *confirmGCStep) Execute(ctx context.Context) ([]nestedStep, error) {
if time.Since(b.lastScheduledTime) < confirmGCInterval {
return nil, fmt.Errorf("wait for reschedule to confirm GC, collection: %d, partition: %d, last scheduled time: %s, now: %s",
b.collectionID, b.partitionID, b.lastScheduledTime.String(), time.Now().String())
}
finished := b.core.broker.GcConfirm(ctx, b.collectionID, b.partitionID)
if finished {
return nil, nil
}
b.lastScheduledTime = time.Now()
return nil, fmt.Errorf("GC is not finished, collection: %d, partition: %d, last scheduled time: %s, now: %s",
b.collectionID, b.partitionID, b.lastScheduledTime.String(), time.Now().String())
}
func (b *confirmGCStep) Desc() string {
return fmt.Sprintf("wait for GC finished, collection: %d, partition: %d, last scheduled time: %s, now: %s",
b.collectionID, b.partitionID, b.lastScheduledTime.String(), time.Now().String())
}
func (b *confirmGCStep) Weight() stepPriority {
return stepPriorityLow
}

View File

@ -2,6 +2,7 @@ package rootcoord
import (
"context"
"sort"
"sync"
"time"
@ -25,14 +26,26 @@ type stepStack struct {
steps []nestedStep
}
func (s *stepStack) totalPriority() int {
total := 0
for _, step := range s.steps {
total += int(step.Weight())
}
return total
}
func (s *stepStack) Execute(ctx context.Context) *stepStack {
steps := s.steps
for len(steps) > 0 {
l := len(steps)
todo := steps[l-1]
childSteps, err := todo.Execute(ctx)
// TODO: maybe a interface `step.LogOnError` is better.
_, skipLog := todo.(*waitForTsSyncedStep)
_, isWaitForTsSyncedStep := todo.(*waitForTsSyncedStep)
_, isConfirmGCStep := todo.(*confirmGCStep)
skipLog := isWaitForTsSyncedStep || isConfirmGCStep
if retry.IsUnRecoverable(err) {
if !skipLog {
log.Warn("failed to execute step, not able to reschedule", zap.Error(err), zap.String("step", todo.Desc()))
@ -76,8 +89,28 @@ func randomSelectPolicy(parallel int) selectStepPolicy {
}
}
func selectByPriority(parallel int, m map[*stepStack]struct{}) []*stepStack {
h := make([]*stepStack, 0, len(m))
for k := range m {
h = append(h, k)
}
sort.Slice(h, func(i, j int) bool {
return h[i].totalPriority() > h[j].totalPriority()
})
if len(h) <= parallel {
return h
}
return h[:parallel]
}
func selectByPriorityPolicy(parallel int) selectStepPolicy {
return func(m map[*stepStack]struct{}) []*stepStack {
return selectByPriority(parallel, m)
}
}
func defaultSelectPolicy() selectStepPolicy {
return randomSelectPolicy(defaultBgExecutingParallel)
return selectByPriorityPolicy(defaultBgExecutingParallel)
}
type bgOpt func(*bgStepExecutor)

View File

@ -8,7 +8,6 @@ import (
"time"
"github.com/milvus-io/milvus/internal/util/retry"
"github.com/stretchr/testify/assert"
)
@ -128,7 +127,7 @@ func Test_randomSelect(t *testing.T) {
func Test_bgStepExecutor_scheduleLoop(t *testing.T) {
bg := newBgStepExecutor(context.Background(),
withSelectStepPolicy(defaultSelectPolicy()),
withSelectStepPolicy(randomSelectPolicy(defaultBgExecutingParallel)),
withBgInterval(time.Millisecond*10))
bg.Start()
n := 20
@ -173,3 +172,43 @@ func Test_bgStepExecutor_scheduleLoop(t *testing.T) {
}
bg.Stop()
}
func Test_selectByPriorityPolicy(t *testing.T) {
policy := selectByPriorityPolicy(4)
t.Run("select all", func(t *testing.T) {
m := map[*stepStack]struct{}{
{steps: []nestedStep{}}: {},
{steps: []nestedStep{}}: {},
}
selected := policy(m)
assert.Equal(t, 2, len(selected))
})
t.Run("select by priority", func(t *testing.T) {
steps := []nestedStep{
&releaseCollectionStep{},
&releaseCollectionStep{},
&releaseCollectionStep{},
&releaseCollectionStep{},
&releaseCollectionStep{},
}
s1 := &stepStack{steps: steps[0:1]}
s2 := &stepStack{steps: steps[0:2]}
s3 := &stepStack{steps: steps[0:3]}
s4 := &stepStack{steps: steps[0:4]}
s5 := &stepStack{steps: steps[0:5]}
m := map[*stepStack]struct{}{
s1: {},
s2: {},
s3: {},
s4: {},
s5: {},
}
selected := policy(m)
assert.Equal(t, 4, len(selected))
for i := 1; i < len(selected); i++ {
assert.True(t, selected[i].totalPriority() <= selected[i-1].totalPriority())
}
})
}

View File

@ -3,6 +3,7 @@ package rootcoord
import (
"context"
"testing"
"time"
"github.com/stretchr/testify/assert"
)
@ -27,3 +28,54 @@ func Test_waitForTsSyncedStep_Execute(t *testing.T) {
assert.Equal(t, 0, len(children))
assert.NoError(t, err)
}
func restoreConfirmGCInterval() {
confirmGCInterval = time.Minute * 20
}
func Test_confirmGCStep_Execute(t *testing.T) {
t.Run("wait for reschedule", func(t *testing.T) {
confirmGCInterval = time.Minute * 1000
defer restoreConfirmGCInterval()
s := &confirmGCStep{lastScheduledTime: time.Now()}
_, err := s.Execute(context.TODO())
assert.Error(t, err)
})
t.Run("GC not finished", func(t *testing.T) {
broker := newMockBroker()
broker.GCConfirmFunc = func(ctx context.Context, collectionID, partitionID UniqueID) bool {
return false
}
core := newTestCore(withBroker(broker))
confirmGCInterval = time.Millisecond
defer restoreConfirmGCInterval()
s := newConfirmGCStep(core, 100, 1000)
time.Sleep(confirmGCInterval)
_, err := s.Execute(context.TODO())
assert.Error(t, err)
})
t.Run("normal case", func(t *testing.T) {
broker := newMockBroker()
broker.GCConfirmFunc = func(ctx context.Context, collectionID, partitionID UniqueID) bool {
return true
}
core := newTestCore(withBroker(broker))
confirmGCInterval = time.Millisecond
defer restoreConfirmGCInterval()
s := newConfirmGCStep(core, 100, 1000)
time.Sleep(confirmGCInterval)
_, err := s.Execute(context.TODO())
assert.NoError(t, err)
})
}

View File

@ -330,6 +330,8 @@ type DataCoord interface {
BroadcastAlteredCollection(ctx context.Context, req *datapb.AlterCollectionRequest) (*commonpb.Status, error)
CheckHealth(ctx context.Context, req *milvuspb.CheckHealthRequest) (*milvuspb.CheckHealthResponse, error)
GcConfirm(ctx context.Context, request *datapb.GcConfirmRequest) (*datapb.GcConfirmResponse, error)
}
// DataCoordComponent defines the interface of DataCoord component.

View File

@ -19,16 +19,17 @@ package mock
import (
"context"
"google.golang.org/grpc"
"github.com/milvus-io/milvus-proto/go-api/commonpb"
"github.com/milvus-io/milvus-proto/go-api/milvuspb"
"github.com/milvus-io/milvus/internal/proto/datapb"
"github.com/milvus-io/milvus/internal/proto/internalpb"
"github.com/milvus-io/milvus/internal/types"
"google.golang.org/grpc"
)
// DataCoordClient mocks of DataCoordClient
type DataCoordClient struct {
types.DataCoord
Err error
}

View File

@ -34,6 +34,10 @@ type GrpcDataCoordClient struct {
Err error
}
func (m *GrpcDataCoordClient) GcConfirm(ctx context.Context, in *datapb.GcConfirmRequest, opts ...grpc.CallOption) (*datapb.GcConfirmResponse, error) {
return &datapb.GcConfirmResponse{}, m.Err
}
func (m *GrpcDataCoordClient) CheckHealth(ctx context.Context, in *milvuspb.CheckHealthRequest, opts ...grpc.CallOption) (*milvuspb.CheckHealthResponse, error) {
return &milvuspb.CheckHealthResponse{}, m.Err
}