2021-11-08 11:49:07 +00:00
// Licensed to the LF AI & Data foundation under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package datanode
import (
"context"
2021-11-11 12:56:49 +00:00
"sync"
2021-11-08 11:49:07 +00:00
"go.uber.org/zap"
2022-02-28 11:11:55 +00:00
2022-10-20 08:39:29 +00:00
"github.com/milvus-io/milvus/internal/proto/datapb"
2023-04-06 11:14:32 +00:00
"github.com/milvus-io/milvus/pkg/log"
2021-11-08 11:49:07 +00:00
)
const (
maxTaskNum = 1024
)
type compactionExecutor struct {
2023-03-17 09:27:56 +00:00
executing sync . Map // planID to compactor
completedCompactor sync . Map // planID to compactor
completed sync . Map // planID to CompactionResult
taskCh chan compactor
dropped sync . Map // vchannel dropped
2021-11-08 11:49:07 +00:00
}
func newCompactionExecutor ( ) * compactionExecutor {
return & compactionExecutor {
2022-08-23 07:50:52 +00:00
executing : sync . Map { } ,
taskCh : make ( chan compactor , maxTaskNum ) ,
2021-11-08 11:49:07 +00:00
}
}
func ( c * compactionExecutor ) execute ( task compactor ) {
c . taskCh <- task
2023-02-15 08:00:33 +00:00
c . toExecutingState ( task )
2021-11-08 11:49:07 +00:00
}
2022-01-18 09:49:39 +00:00
func ( c * compactionExecutor ) toExecutingState ( task compactor ) {
c . executing . Store ( task . getPlanID ( ) , task )
}
func ( c * compactionExecutor ) toCompleteState ( task compactor ) {
task . complete ( )
c . executing . Delete ( task . getPlanID ( ) )
}
2023-06-20 02:20:41 +00:00
func ( c * compactionExecutor ) injectDone ( planID UniqueID , success bool ) {
2023-03-17 09:27:56 +00:00
c . completed . Delete ( planID )
task , loaded := c . completedCompactor . LoadAndDelete ( planID )
if loaded {
2023-06-20 02:20:41 +00:00
task . ( compactor ) . injectDone ( success )
2023-03-17 09:27:56 +00:00
}
}
2022-01-18 09:49:39 +00:00
// These two func are bounded for waitGroup
func ( c * compactionExecutor ) executeWithState ( task compactor ) {
go c . executeTask ( task )
}
2021-11-08 11:49:07 +00:00
func ( c * compactionExecutor ) start ( ctx context . Context ) {
for {
select {
case <- ctx . Done ( ) :
return
case task := <- c . taskCh :
2022-01-18 09:49:39 +00:00
c . executeWithState ( task )
2021-11-08 11:49:07 +00:00
}
}
}
func ( c * compactionExecutor ) executeTask ( task compactor ) {
defer func ( ) {
2022-01-18 09:49:39 +00:00
c . toCompleteState ( task )
2021-11-08 11:49:07 +00:00
} ( )
2023-06-19 06:18:41 +00:00
log . Info ( "start to execute compaction" , zap . Int64 ( "planID" , task . getPlanID ( ) ) , zap . Int64 ( "Collection" , task . getCollection ( ) ) , zap . String ( "channel" , task . getChannelName ( ) ) )
2021-11-08 11:49:07 +00:00
2022-08-23 07:50:52 +00:00
result , err := task . compact ( )
2021-11-08 11:49:07 +00:00
if err != nil {
log . Warn ( "compaction task failed" ,
zap . Int64 ( "planID" , task . getPlanID ( ) ) ,
zap . Error ( err ) ,
)
2022-08-23 07:50:52 +00:00
} else {
c . completed . Store ( task . getPlanID ( ) , result )
2023-03-17 09:27:56 +00:00
c . completedCompactor . Store ( task . getPlanID ( ) , task )
2021-11-08 11:49:07 +00:00
}
log . Info ( "end to execute compaction" , zap . Int64 ( "planID" , task . getPlanID ( ) ) )
}
2021-11-11 12:56:49 +00:00
func ( c * compactionExecutor ) stopTask ( planID UniqueID ) {
task , loaded := c . executing . LoadAndDelete ( planID )
if loaded {
2022-01-25 05:29:40 +00:00
log . Warn ( "compaction executor stop task" , zap . Int64 ( "planID" , planID ) , zap . String ( "vChannelName" , task . ( compactor ) . getChannelName ( ) ) )
2021-11-11 12:56:49 +00:00
task . ( compactor ) . stop ( )
}
}
2021-12-02 08:39:33 +00:00
func ( c * compactionExecutor ) channelValidateForCompaction ( vChannelName string ) bool {
// if vchannel marked dropped, compaction should not proceed
_ , loaded := c . dropped . Load ( vChannelName )
return ! loaded
}
2021-11-25 01:43:15 +00:00
func ( c * compactionExecutor ) stopExecutingtaskByVChannelName ( vChannelName string ) {
2021-12-02 08:39:33 +00:00
c . dropped . Store ( vChannelName , struct { } { } )
2021-11-11 12:56:49 +00:00
c . executing . Range ( func ( key interface { } , value interface { } ) bool {
2021-12-02 08:39:33 +00:00
if value . ( compactor ) . getChannelName ( ) == vChannelName {
2021-11-11 12:56:49 +00:00
c . stopTask ( key . ( UniqueID ) )
}
return true
} )
2022-10-20 08:39:29 +00:00
// remove all completed plans for vChannelName
c . completed . Range ( func ( key interface { } , value interface { } ) bool {
if value . ( * datapb . CompactionResult ) . GetChannel ( ) == vChannelName {
2023-06-20 02:20:41 +00:00
c . injectDone ( key . ( UniqueID ) , true )
2022-10-20 08:39:29 +00:00
log . Info ( "remove compaction results for dropped channel" ,
zap . String ( "channel" , vChannelName ) ,
zap . Int64 ( "planID" , key . ( UniqueID ) ) )
}
return true
} )
2021-11-11 12:56:49 +00:00
}