2021-04-19 13:47:10 +08:00
|
|
|
// Copyright (C) 2019-2020 Zilliz. All rights reserved.
|
|
|
|
//
|
|
|
|
// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance
|
|
|
|
// with the License. You may obtain a copy of the License at
|
|
|
|
//
|
|
|
|
// http://www.apache.org/licenses/LICENSE-2.0
|
|
|
|
//
|
|
|
|
// Unless required by applicable law or agreed to in writing, software distributed under the License
|
|
|
|
// is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
|
|
|
|
// or implied. See the License for the specific language governing permissions and limitations under the License.
|
|
|
|
|
2021-01-16 10:12:14 +08:00
|
|
|
package querynode
|
2020-12-24 20:55:40 +08:00
|
|
|
|
|
|
|
import (
|
|
|
|
"context"
|
2021-03-22 16:36:10 +08:00
|
|
|
"errors"
|
2020-12-24 20:55:40 +08:00
|
|
|
"fmt"
|
2021-02-06 11:35:35 +08:00
|
|
|
"sync"
|
2020-12-29 14:43:40 +08:00
|
|
|
"time"
|
2020-12-24 20:55:40 +08:00
|
|
|
|
2021-03-05 09:21:35 +08:00
|
|
|
"go.uber.org/zap"
|
|
|
|
|
2021-04-22 14:45:57 +08:00
|
|
|
"github.com/milvus-io/milvus/internal/log"
|
|
|
|
"github.com/milvus-io/milvus/internal/proto/commonpb"
|
|
|
|
"github.com/milvus-io/milvus/internal/types"
|
2020-12-24 20:55:40 +08:00
|
|
|
)
|
|
|
|
|
2021-02-20 10:14:03 +08:00
|
|
|
const loadingCheckInterval = 3
|
2021-01-30 16:02:10 +08:00
|
|
|
|
|
|
|
type loadService struct {
|
2020-12-24 20:55:40 +08:00
|
|
|
ctx context.Context
|
|
|
|
cancel context.CancelFunc
|
|
|
|
|
2021-02-06 11:35:35 +08:00
|
|
|
segLoader *segmentLoader
|
2021-01-19 11:37:16 +08:00
|
|
|
}
|
|
|
|
|
2021-02-02 19:54:31 +08:00
|
|
|
// -------------------------------------------- load index -------------------------------------------- //
|
|
|
|
func (s *loadService) start() {
|
2021-02-06 11:35:35 +08:00
|
|
|
wg := &sync.WaitGroup{}
|
2021-01-30 16:02:10 +08:00
|
|
|
for {
|
|
|
|
select {
|
2021-02-02 19:54:31 +08:00
|
|
|
case <-s.ctx.Done():
|
2021-01-30 16:02:10 +08:00
|
|
|
return
|
2021-02-20 10:14:03 +08:00
|
|
|
case <-time.After(loadingCheckInterval * time.Second):
|
2021-02-06 11:35:35 +08:00
|
|
|
wg.Add(2)
|
2021-04-07 18:29:19 +08:00
|
|
|
//go s.segLoader.indexLoader.doLoadIndex(wg)
|
2021-02-06 11:35:35 +08:00
|
|
|
go s.loadSegmentActively(wg)
|
|
|
|
wg.Wait()
|
2021-01-18 10:38:41 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-02-02 19:54:31 +08:00
|
|
|
func (s *loadService) close() {
|
|
|
|
s.cancel()
|
2021-01-12 18:03:24 +08:00
|
|
|
}
|
|
|
|
|
2021-02-06 11:35:35 +08:00
|
|
|
func (s *loadService) loadSegmentActively(wg *sync.WaitGroup) {
|
2021-03-12 19:23:06 +08:00
|
|
|
collectionIDs, partitionIDs, segmentIDs := s.segLoader.replica.getSegmentsToLoadBySegmentType(segmentTypeGrowing)
|
2021-02-06 11:35:35 +08:00
|
|
|
if len(collectionIDs) <= 0 {
|
2021-02-07 10:29:58 +08:00
|
|
|
wg.Done()
|
2021-02-06 11:35:35 +08:00
|
|
|
return
|
2020-12-24 20:55:40 +08:00
|
|
|
}
|
2021-03-05 09:21:35 +08:00
|
|
|
log.Debug("do load segment for growing segments:", zap.String("segmentIDs", fmt.Sprintln(segmentIDs)))
|
2021-02-06 11:35:35 +08:00
|
|
|
for i := range collectionIDs {
|
2021-04-07 18:29:19 +08:00
|
|
|
collection, err := s.segLoader.replica.getCollectionByID(collectionIDs[i])
|
|
|
|
if err != nil {
|
|
|
|
log.Warn(err.Error())
|
|
|
|
}
|
|
|
|
|
2021-02-06 11:35:35 +08:00
|
|
|
fieldIDs, err := s.segLoader.replica.getFieldIDsByCollectionID(collectionIDs[i])
|
2020-12-24 20:55:40 +08:00
|
|
|
if err != nil {
|
2021-03-05 09:21:35 +08:00
|
|
|
log.Error(err.Error())
|
2021-02-06 11:35:35 +08:00
|
|
|
continue
|
2020-12-24 20:55:40 +08:00
|
|
|
}
|
2021-04-07 18:29:19 +08:00
|
|
|
segment := newSegment(collection, segmentIDs[i], partitionIDs[i], collectionIDs[i], segmentTypeSealed)
|
|
|
|
segment.setLoadBinLogEnable(true)
|
|
|
|
err = s.loadSegmentInternal(collectionIDs[i], segment, fieldIDs)
|
|
|
|
if err == nil {
|
|
|
|
// replace segment
|
|
|
|
err = s.segLoader.replica.replaceGrowingSegmentBySealedSegment(segment)
|
|
|
|
}
|
2020-12-24 20:55:40 +08:00
|
|
|
if err != nil {
|
2021-04-07 18:29:19 +08:00
|
|
|
deleteSegment(segment)
|
2021-03-05 09:21:35 +08:00
|
|
|
log.Error(err.Error())
|
2020-12-24 20:55:40 +08:00
|
|
|
}
|
|
|
|
}
|
2021-02-06 11:35:35 +08:00
|
|
|
// sendQueryNodeStats
|
|
|
|
err := s.segLoader.indexLoader.sendQueryNodeStats()
|
2020-12-24 20:55:40 +08:00
|
|
|
if err != nil {
|
2021-03-05 09:21:35 +08:00
|
|
|
log.Error(err.Error())
|
2021-02-06 11:35:35 +08:00
|
|
|
wg.Done()
|
|
|
|
return
|
2020-12-24 20:55:40 +08:00
|
|
|
}
|
|
|
|
|
2021-02-06 11:35:35 +08:00
|
|
|
wg.Done()
|
2020-12-24 20:55:40 +08:00
|
|
|
}
|
2021-01-12 18:03:24 +08:00
|
|
|
|
2021-02-06 11:35:35 +08:00
|
|
|
// load segment passively
|
2021-03-22 16:36:10 +08:00
|
|
|
func (s *loadService) loadSegmentPassively(collectionID UniqueID, partitionID UniqueID, segmentIDs []UniqueID, fieldIDs []int64) error {
|
2021-02-02 19:54:31 +08:00
|
|
|
// TODO: interim solution
|
|
|
|
if len(fieldIDs) == 0 {
|
2021-02-06 11:35:35 +08:00
|
|
|
var err error
|
|
|
|
fieldIDs, err = s.segLoader.replica.getFieldIDsByCollectionID(collectionID)
|
2021-02-02 19:54:31 +08:00
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
}
|
|
|
|
for _, segmentID := range segmentIDs {
|
2021-04-07 18:29:19 +08:00
|
|
|
collection, err := s.segLoader.replica.getCollectionByID(collectionID)
|
2021-02-23 14:13:33 +08:00
|
|
|
if err != nil {
|
2021-04-07 18:29:19 +08:00
|
|
|
return err
|
2021-02-23 14:13:33 +08:00
|
|
|
}
|
2021-04-07 18:29:19 +08:00
|
|
|
_, err = s.segLoader.replica.getPartitionByID(partitionID)
|
2021-03-12 19:23:06 +08:00
|
|
|
if err != nil {
|
2021-04-07 18:29:19 +08:00
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
segment := newSegment(collection, segmentID, partitionID, collectionID, segmentTypeSealed)
|
|
|
|
segment.setLoadBinLogEnable(true)
|
|
|
|
err = s.loadSegmentInternal(collectionID, segment, fieldIDs)
|
|
|
|
if err == nil {
|
|
|
|
err = s.segLoader.replica.setSegment(segment)
|
2021-03-12 19:23:06 +08:00
|
|
|
}
|
2021-02-02 19:54:31 +08:00
|
|
|
if err != nil {
|
2021-03-05 09:21:35 +08:00
|
|
|
log.Warn(err.Error())
|
2021-04-07 18:29:19 +08:00
|
|
|
err = s.addSegmentToLoadBuffer(segment)
|
|
|
|
if err != nil {
|
|
|
|
log.Warn(err.Error())
|
|
|
|
}
|
2021-02-02 19:54:31 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
2021-04-07 18:29:19 +08:00
|
|
|
func (s *loadService) addSegmentToLoadBuffer(segment *Segment) error {
|
|
|
|
segmentID := segment.segmentID
|
|
|
|
partitionID := segment.partitionID
|
|
|
|
collectionID := segment.collectionID
|
|
|
|
deleteSegment(segment)
|
|
|
|
err := s.segLoader.replica.addSegment(segmentID, partitionID, collectionID, segmentTypeGrowing)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
err = s.segLoader.replica.setSegmentEnableLoadBinLog(segmentID, true)
|
|
|
|
if err != nil {
|
|
|
|
s.segLoader.replica.removeSegment(segmentID)
|
|
|
|
}
|
|
|
|
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
func (s *loadService) loadSegmentInternal(collectionID UniqueID, segment *Segment, fieldIDs []int64) error {
|
2021-02-07 21:26:03 +08:00
|
|
|
// create segment
|
2021-04-07 18:29:19 +08:00
|
|
|
statesResp, err := s.segLoader.GetSegmentStates(segment.segmentID)
|
2021-02-23 14:13:33 +08:00
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
2021-03-11 14:14:29 +08:00
|
|
|
if statesResp.States[0].State != commonpb.SegmentState_Flushed {
|
2021-02-23 14:13:33 +08:00
|
|
|
return errors.New("segment not flush done")
|
|
|
|
}
|
|
|
|
|
2021-04-07 18:29:19 +08:00
|
|
|
insertBinlogPaths, srcFieldIDs, err := s.segLoader.getInsertBinlogPaths(segment.segmentID)
|
2021-02-07 21:26:03 +08:00
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
2021-04-07 18:29:19 +08:00
|
|
|
vectorFieldIDs, err := s.segLoader.replica.getVecFieldIDsByCollectionID(collectionID)
|
2021-02-07 21:26:03 +08:00
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
2021-04-07 18:29:19 +08:00
|
|
|
|
|
|
|
loadIndexFieldIDs := make([]int64, 0)
|
|
|
|
for _, vecFieldID := range vectorFieldIDs {
|
|
|
|
err = s.segLoader.indexLoader.setIndexInfo(collectionID, segment, vecFieldID)
|
2021-02-02 19:54:31 +08:00
|
|
|
if err != nil {
|
2021-04-07 18:29:19 +08:00
|
|
|
log.Warn(err.Error())
|
|
|
|
continue
|
2021-02-02 19:54:31 +08:00
|
|
|
}
|
2021-04-07 18:29:19 +08:00
|
|
|
loadIndexFieldIDs = append(loadIndexFieldIDs, vecFieldID)
|
2021-02-02 19:54:31 +08:00
|
|
|
}
|
2021-04-07 18:29:19 +08:00
|
|
|
// we don't need load to vector fields
|
|
|
|
fieldIDs = s.segLoader.filterOutVectorFields(fieldIDs, loadIndexFieldIDs)
|
2021-02-02 19:54:31 +08:00
|
|
|
|
2021-03-05 09:21:35 +08:00
|
|
|
//log.Debug("srcFieldIDs in internal:", srcFieldIDs)
|
|
|
|
//log.Debug("dstFieldIDs in internal:", fieldIDs)
|
2021-04-07 18:29:19 +08:00
|
|
|
targetFields, err := s.segLoader.checkTargetFields(insertBinlogPaths, srcFieldIDs, fieldIDs)
|
2021-02-22 16:34:15 +08:00
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
2021-04-07 18:29:19 +08:00
|
|
|
log.Debug("loading insert...")
|
2021-02-07 21:26:03 +08:00
|
|
|
err = s.segLoader.loadSegmentFieldsData(segment, targetFields)
|
2021-02-02 19:54:31 +08:00
|
|
|
if err != nil {
|
2021-02-06 11:35:35 +08:00
|
|
|
return err
|
2021-02-02 19:54:31 +08:00
|
|
|
}
|
2021-04-07 18:29:19 +08:00
|
|
|
for _, id := range loadIndexFieldIDs {
|
2021-03-05 09:21:35 +08:00
|
|
|
log.Debug("loading index...")
|
2021-04-07 18:29:19 +08:00
|
|
|
err = s.segLoader.indexLoader.loadIndex(segment, id)
|
2021-02-06 11:35:35 +08:00
|
|
|
if err != nil {
|
|
|
|
return err
|
2021-02-02 19:54:31 +08:00
|
|
|
}
|
|
|
|
}
|
2021-04-07 18:29:19 +08:00
|
|
|
|
2021-02-07 21:26:03 +08:00
|
|
|
return nil
|
2021-01-12 18:03:24 +08:00
|
|
|
}
|
2021-01-30 16:02:10 +08:00
|
|
|
|
2021-03-22 16:36:10 +08:00
|
|
|
func newLoadService(ctx context.Context, masterService types.MasterService, dataService types.DataService, indexService types.IndexService, replica ReplicaInterface) *loadService {
|
2021-01-30 16:02:10 +08:00
|
|
|
ctx1, cancel := context.WithCancel(ctx)
|
|
|
|
|
2021-03-22 16:36:10 +08:00
|
|
|
segLoader := newSegmentLoader(ctx1, masterService, indexService, dataService, replica)
|
2021-01-30 16:02:10 +08:00
|
|
|
|
|
|
|
return &loadService{
|
|
|
|
ctx: ctx1,
|
|
|
|
cancel: cancel,
|
|
|
|
|
2021-02-06 11:35:35 +08:00
|
|
|
segLoader: segLoader,
|
2021-01-30 16:02:10 +08:00
|
|
|
}
|
|
|
|
}
|