2021-11-08 19:49:07 +08: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"
"go.uber.org/zap"
2022-02-28 19:11:55 +08:00
2022-10-20 16:39:29 +08:00
"github.com/milvus-io/milvus/internal/proto/datapb"
2023-04-06 19:14:32 +08:00
"github.com/milvus-io/milvus/pkg/log"
2023-07-24 10:23:01 +08:00
"github.com/milvus-io/milvus/pkg/util/typeutil"
2021-11-08 19:49:07 +08:00
)
const (
maxTaskNum = 1024
)
type compactionExecutor struct {
2023-07-24 10:23:01 +08:00
executing * typeutil . ConcurrentMap [ int64 , compactor ] // planID to compactor
completedCompactor * typeutil . ConcurrentMap [ int64 , compactor ] // planID to compactor
completed * typeutil . ConcurrentMap [ int64 , * datapb . CompactionResult ] // planID to CompactionResult
2023-03-17 17:27:56 +08:00
taskCh chan compactor
2023-07-24 10:23:01 +08:00
dropped * typeutil . ConcurrentSet [ string ] // vchannel dropped
2021-11-08 19:49:07 +08:00
}
func newCompactionExecutor ( ) * compactionExecutor {
return & compactionExecutor {
2023-07-24 10:23:01 +08:00
executing : typeutil . NewConcurrentMap [ int64 , compactor ] ( ) ,
completedCompactor : typeutil . NewConcurrentMap [ int64 , compactor ] ( ) ,
completed : typeutil . NewConcurrentMap [ int64 , * datapb . CompactionResult ] ( ) ,
taskCh : make ( chan compactor , maxTaskNum ) ,
dropped : typeutil . NewConcurrentSet [ string ] ( ) ,
2021-11-08 19:49:07 +08:00
}
}
func ( c * compactionExecutor ) execute ( task compactor ) {
c . taskCh <- task
2023-02-15 16:00:33 +08:00
c . toExecutingState ( task )
2021-11-08 19:49:07 +08:00
}
2022-01-18 17:49:39 +08:00
func ( c * compactionExecutor ) toExecutingState ( task compactor ) {
2023-07-24 10:23:01 +08:00
c . executing . Insert ( task . getPlanID ( ) , task )
2022-01-18 17:49:39 +08:00
}
func ( c * compactionExecutor ) toCompleteState ( task compactor ) {
task . complete ( )
2023-07-24 10:23:01 +08:00
c . executing . GetAndRemove ( task . getPlanID ( ) )
2022-01-18 17:49:39 +08:00
}
2023-06-20 10:20:41 +08:00
func ( c * compactionExecutor ) injectDone ( planID UniqueID , success bool ) {
2023-07-24 10:23:01 +08:00
c . completed . GetAndRemove ( planID )
task , loaded := c . completedCompactor . GetAndRemove ( planID )
2023-03-17 17:27:56 +08:00
if loaded {
2023-07-24 10:23:01 +08:00
task . injectDone ( success )
2023-03-17 17:27:56 +08:00
}
}
2022-01-18 17:49:39 +08:00
// These two func are bounded for waitGroup
func ( c * compactionExecutor ) executeWithState ( task compactor ) {
go c . executeTask ( task )
}
2021-11-08 19:49:07 +08:00
func ( c * compactionExecutor ) start ( ctx context . Context ) {
for {
select {
case <- ctx . Done ( ) :
return
case task := <- c . taskCh :
2022-01-18 17:49:39 +08:00
c . executeWithState ( task )
2021-11-08 19:49:07 +08:00
}
}
}
func ( c * compactionExecutor ) executeTask ( task compactor ) {
defer func ( ) {
2022-01-18 17:49:39 +08:00
c . toCompleteState ( task )
2021-11-08 19:49:07 +08:00
} ( )
2023-06-19 14:18:41 +08: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 19:49:07 +08:00
2022-08-23 15:50:52 +08:00
result , err := task . compact ( )
2021-11-08 19:49:07 +08:00
if err != nil {
log . Warn ( "compaction task failed" ,
zap . Int64 ( "planID" , task . getPlanID ( ) ) ,
zap . Error ( err ) ,
)
2022-08-23 15:50:52 +08:00
} else {
2023-07-24 10:23:01 +08:00
c . completed . Insert ( task . getPlanID ( ) , result )
c . completedCompactor . Insert ( task . getPlanID ( ) , task )
2021-11-08 19:49:07 +08:00
}
log . Info ( "end to execute compaction" , zap . Int64 ( "planID" , task . getPlanID ( ) ) )
}
2021-11-11 20:56:49 +08:00
func ( c * compactionExecutor ) stopTask ( planID UniqueID ) {
2023-07-24 10:23:01 +08:00
task , loaded := c . executing . GetAndRemove ( planID )
2021-11-11 20:56:49 +08:00
if loaded {
2023-07-24 10:23:01 +08:00
log . Warn ( "compaction executor stop task" , zap . Int64 ( "planID" , planID ) , zap . String ( "vChannelName" , task . getChannelName ( ) ) )
task . stop ( )
2021-11-11 20:56:49 +08:00
}
}
2021-12-02 16:39:33 +08:00
func ( c * compactionExecutor ) channelValidateForCompaction ( vChannelName string ) bool {
// if vchannel marked dropped, compaction should not proceed
2023-07-24 10:23:01 +08:00
return ! c . dropped . Contain ( vChannelName )
2021-12-02 16:39:33 +08:00
}
2021-11-25 09:43:15 +08:00
func ( c * compactionExecutor ) stopExecutingtaskByVChannelName ( vChannelName string ) {
2023-07-24 10:23:01 +08:00
c . dropped . Insert ( vChannelName )
c . executing . Range ( func ( planID int64 , task compactor ) bool {
if task . getChannelName ( ) == vChannelName {
c . stopTask ( planID )
2021-11-11 20:56:49 +08:00
}
return true
} )
2022-10-20 16:39:29 +08:00
// remove all completed plans for vChannelName
2023-07-24 10:23:01 +08:00
c . completed . Range ( func ( planID int64 , result * datapb . CompactionResult ) bool {
if result . GetChannel ( ) == vChannelName {
c . injectDone ( planID , true )
2022-10-20 16:39:29 +08:00
log . Info ( "remove compaction results for dropped channel" ,
zap . String ( "channel" , vChannelName ) ,
2023-07-24 10:23:01 +08:00
zap . Int64 ( "planID" , planID ) )
2022-10-20 16:39:29 +08:00
}
return true
} )
2021-11-11 20:56:49 +08:00
}