2021-10-27 18:04:47 +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
2021-01-19 18:32:57 +08:00
// with the License. You may obtain a copy of the License at
//
2021-10-27 18:04:47 +08:00
// http://www.apache.org/licenses/LICENSE-2.0
2021-01-19 18:32:57 +08:00
//
2021-10-27 18:04:47 +08:00
// 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-19 18:32:57 +08:00
2021-06-21 17:28:03 +08:00
package indexcoord
2021-01-19 18:32:57 +08:00
import (
2021-06-23 09:24:10 +08:00
"context"
2021-09-08 14:23:59 +08:00
"errors"
2021-01-19 18:32:57 +08:00
"fmt"
2022-09-28 11:02:54 +08:00
"strconv"
2021-01-19 18:32:57 +08:00
"sync"
2021-05-27 22:24:29 +08:00
2022-11-08 20:13:03 +08:00
"github.com/milvus-io/milvus/internal/util/timerecord"
2022-09-28 11:02:54 +08:00
"github.com/prometheus/client_golang/prometheus"
2022-08-25 15:48:54 +08:00
"github.com/golang/protobuf/proto"
2021-03-10 09:56:09 +08:00
"go.uber.org/zap"
2022-10-16 20:49:27 +08:00
"github.com/milvus-io/milvus-proto/go-api/commonpb"
2022-10-19 16:55:27 +08:00
"github.com/milvus-io/milvus/internal/common"
2022-08-25 15:48:54 +08:00
"github.com/milvus-io/milvus/internal/kv"
2021-04-22 14:45:57 +08:00
"github.com/milvus-io/milvus/internal/log"
2022-08-25 15:48:54 +08:00
"github.com/milvus-io/milvus/internal/metastore"
"github.com/milvus-io/milvus/internal/metastore/kv/indexcoord"
"github.com/milvus-io/milvus/internal/metastore/model"
"github.com/milvus-io/milvus/internal/metrics"
2021-04-22 14:45:57 +08:00
"github.com/milvus-io/milvus/internal/proto/indexpb"
2021-01-19 18:32:57 +08:00
)
2022-08-25 15:48:54 +08:00
// metaTable maintains index-related information
2021-01-19 18:32:57 +08:00
type metaTable struct {
2022-08-25 15:48:54 +08:00
catalog metastore . IndexCoordCatalog
indexLock sync . RWMutex
segmentIndexLock sync . RWMutex
// collectionIndexes records which indexes are on the collection
// collID -> indexID -> index
collectionIndexes map [ UniqueID ] map [ UniqueID ] * model . Index
// segmentIndexes records which indexes are on the segment
// segID -> indexID -> segmentIndex
segmentIndexes map [ UniqueID ] map [ UniqueID ] * model . SegmentIndex
// buildID2Meta records the meta information of the segment
// buildID -> segmentIndex
buildID2SegmentIndex map [ UniqueID ] * model . SegmentIndex
2021-01-19 18:32:57 +08:00
}
2021-09-23 21:37:55 +08:00
// NewMetaTable is used to create a new meta table.
2022-06-27 21:52:17 +08:00
func NewMetaTable ( kv kv . MetaKv ) ( * metaTable , error ) {
2021-01-19 18:32:57 +08:00
mt := & metaTable {
2022-08-25 15:48:54 +08:00
catalog : & indexcoord . Catalog {
Txn : kv ,
} ,
indexLock : sync . RWMutex { } ,
segmentIndexLock : sync . RWMutex { } ,
2021-01-19 18:32:57 +08:00
}
err := mt . reloadFromKV ( )
if err != nil {
return nil , err
}
return mt , nil
}
2022-08-25 15:48:54 +08:00
func ( mt * metaTable ) updateCollectionIndex ( index * model . Index ) {
if _ , ok := mt . collectionIndexes [ index . CollectionID ] ; ! ok {
mt . collectionIndexes [ index . CollectionID ] = make ( map [ UniqueID ] * model . Index )
}
mt . collectionIndexes [ index . CollectionID ] [ index . IndexID ] = index
}
func ( mt * metaTable ) updateSegmentIndex ( segIdx * model . SegmentIndex ) {
if _ , ok := mt . segmentIndexes [ segIdx . SegmentID ] ; ! ok {
mt . segmentIndexes [ segIdx . SegmentID ] = make ( map [ UniqueID ] * model . SegmentIndex )
}
mt . segmentIndexes [ segIdx . SegmentID ] [ segIdx . IndexID ] = segIdx
mt . buildID2SegmentIndex [ segIdx . BuildID ] = segIdx
}
2021-12-08 09:33:41 +08:00
// reloadFromKV reloads the index meta from ETCD.
2021-01-19 18:32:57 +08:00
func ( mt * metaTable ) reloadFromKV ( ) error {
2022-11-08 20:13:03 +08:00
record := timerecord . NewTimeRecorder ( "indexcoord" )
2022-08-25 15:48:54 +08:00
mt . collectionIndexes = make ( map [ UniqueID ] map [ UniqueID ] * model . Index )
mt . segmentIndexes = make ( map [ UniqueID ] map [ UniqueID ] * model . SegmentIndex )
mt . buildID2SegmentIndex = make ( map [ UniqueID ] * model . SegmentIndex )
2021-01-19 18:32:57 +08:00
2022-08-25 15:48:54 +08:00
// load field indexes
log . Info ( "IndexCoord metaTable reloadFromKV load indexes" )
fieldIndexes , err := mt . catalog . ListIndexes ( context . Background ( ) )
2021-01-19 18:32:57 +08:00
if err != nil {
2022-08-25 15:48:54 +08:00
log . Error ( "IndexCoord metaTable reloadFromKV load field indexes fail" , zap . Error ( err ) )
return err
}
segmentIndxes , err := mt . catalog . ListSegmentIndexes ( context . Background ( ) )
if err != nil {
log . Error ( "IndexCoord metaTable reloadFromKV load segment indexes fail" , zap . Error ( err ) )
2021-01-19 18:32:57 +08:00
return err
}
2022-08-25 15:48:54 +08:00
for _ , fieldIndex := range fieldIndexes {
mt . updateCollectionIndex ( fieldIndex )
}
for _ , segIdx := range segmentIndxes {
mt . updateSegmentIndex ( segIdx )
2021-01-19 18:32:57 +08:00
}
2022-08-25 15:48:54 +08:00
log . Info ( "IndexCoord metaTable reloadFromKV success" )
2022-11-08 20:13:03 +08:00
record . Record ( "metaTable reloadFromKV" )
2021-01-19 18:32:57 +08:00
return nil
}
2022-08-25 15:48:54 +08:00
func ( mt * metaTable ) saveFieldIndexMeta ( index * model . Index ) error {
err := mt . catalog . CreateIndex ( context . Background ( ) , index )
2021-09-29 20:26:00 +08:00
if err != nil {
2022-08-25 15:48:54 +08:00
log . Error ( "failed to save index meta in etcd" , zap . Int64 ( "buildID" , index . CollectionID ) ,
zap . Int64 ( "fieldID" , index . FieldID ) , zap . Int64 ( "indexID" , index . IndexID ) , zap . Error ( err ) )
2021-09-29 20:26:00 +08:00
return err
}
2022-08-25 15:48:54 +08:00
mt . updateCollectionIndex ( index )
return nil
}
func ( mt * metaTable ) alterIndexes ( indexes [ ] * model . Index ) error {
err := mt . catalog . AlterIndexes ( context . Background ( ) , indexes )
2021-05-27 22:24:29 +08:00
if err != nil {
2022-08-25 15:48:54 +08:00
log . Error ( "failed to alter index meta in meta store" , zap . Int ( "indexes num" , len ( indexes ) ) , zap . Error ( err ) )
2021-05-27 22:24:29 +08:00
return err
}
2022-08-25 15:48:54 +08:00
for _ , index := range indexes {
mt . updateCollectionIndex ( index )
2022-07-06 13:54:21 +08:00
}
2021-05-27 22:24:29 +08:00
return nil
}
2022-08-25 15:48:54 +08:00
func ( mt * metaTable ) alterSegmentIndexes ( segIdxes [ ] * model . SegmentIndex ) error {
err := mt . catalog . AlterSegmentIndexes ( context . Background ( ) , segIdxes )
2021-05-27 22:24:29 +08:00
if err != nil {
2022-08-25 15:48:54 +08:00
log . Error ( "failed to alter segments index in meta store" , zap . Int ( "segment indexes num" , len ( segIdxes ) ) ,
zap . Error ( err ) )
return err
2021-05-27 22:24:29 +08:00
}
2022-08-25 15:48:54 +08:00
for _ , segIdx := range segIdxes {
mt . updateSegmentIndex ( segIdx )
2021-09-08 14:23:59 +08:00
}
2022-08-25 15:48:54 +08:00
return nil
}
// saveSegmentIndexMeta saves the index meta to ETCD.
// metaTable.lock.Lock() before call this function
func ( mt * metaTable ) saveSegmentIndexMeta ( segIdx * model . SegmentIndex ) error {
err := mt . catalog . CreateSegmentIndex ( context . Background ( ) , segIdx )
2021-05-27 22:24:29 +08:00
if err != nil {
2022-08-25 15:48:54 +08:00
log . Error ( "failed to save index meta in etcd" , zap . Int64 ( "buildID" , segIdx . BuildID ) , zap . Error ( err ) )
return err
2021-05-27 22:24:29 +08:00
}
2021-01-19 18:32:57 +08:00
2022-08-25 15:48:54 +08:00
mt . updateSegmentIndex ( segIdx )
log . Info ( "IndexCoord metaTable saveIndexMeta success" , zap . Int64 ( "buildID" , segIdx . BuildID ) )
return nil
}
func ( mt * metaTable ) updateIndexMeta ( index * model . Index , updateFunc func ( clonedIndex * model . Index ) error ) error {
return updateFunc ( model . CloneIndex ( index ) )
}
func ( mt * metaTable ) updateSegIndexMeta ( segIdx * model . SegmentIndex , updateFunc func ( clonedSegIdx * model . SegmentIndex ) error ) error {
return updateFunc ( model . CloneSegmentIndex ( segIdx ) )
2021-01-19 18:32:57 +08:00
}
2022-09-28 11:02:54 +08:00
func ( mt * metaTable ) updateIndexTasksMetrics ( ) {
taskMetrics := make ( map [ UniqueID ] map [ commonpb . IndexState ] int )
for _ , segIdx := range mt . buildID2SegmentIndex {
if segIdx . IsDeleted {
continue
}
if _ , ok := taskMetrics [ segIdx . CollectionID ] ; ! ok {
taskMetrics [ segIdx . CollectionID ] = make ( map [ commonpb . IndexState ] int )
taskMetrics [ segIdx . CollectionID ] [ commonpb . IndexState_Unissued ] = 0
taskMetrics [ segIdx . CollectionID ] [ commonpb . IndexState_InProgress ] = 0
taskMetrics [ segIdx . CollectionID ] [ commonpb . IndexState_Finished ] = 0
taskMetrics [ segIdx . CollectionID ] [ commonpb . IndexState_Failed ] = 0
}
taskMetrics [ segIdx . CollectionID ] [ segIdx . IndexState ] ++
}
for collID , m := range taskMetrics {
for k , v := range m {
switch k {
case commonpb . IndexState_Unissued :
metrics . IndexCoordIndexTaskNum . WithLabelValues ( strconv . FormatInt ( collID , 10 ) , metrics . UnissuedIndexTaskLabel ) . Set ( float64 ( v ) )
case commonpb . IndexState_InProgress :
metrics . IndexCoordIndexTaskNum . WithLabelValues ( strconv . FormatInt ( collID , 10 ) , metrics . InProgressIndexTaskLabel ) . Set ( float64 ( v ) )
case commonpb . IndexState_Finished :
metrics . IndexCoordIndexTaskNum . WithLabelValues ( strconv . FormatInt ( collID , 10 ) , metrics . FinishedIndexTaskLabel ) . Set ( float64 ( v ) )
case commonpb . IndexState_Failed :
metrics . IndexCoordIndexTaskNum . WithLabelValues ( strconv . FormatInt ( collID , 10 ) , metrics . FailedIndexTaskLabel ) . Set ( float64 ( v ) )
}
}
}
}
2022-08-25 15:48:54 +08:00
func ( mt * metaTable ) GetAllIndexMeta ( ) map [ int64 ] * model . SegmentIndex {
mt . segmentIndexLock . RLock ( )
defer mt . segmentIndexLock . RUnlock ( )
2022-07-07 14:44:21 +08:00
2022-08-25 15:48:54 +08:00
metas := map [ int64 ] * model . SegmentIndex { }
for buildID , segIdx := range mt . buildID2SegmentIndex {
metas [ buildID ] = model . CloneSegmentIndex ( segIdx )
2022-07-07 14:44:21 +08:00
}
return metas
}
2022-08-25 15:48:54 +08:00
func ( mt * metaTable ) GetMeta ( buildID UniqueID ) ( * model . SegmentIndex , bool ) {
mt . segmentIndexLock . RLock ( )
defer mt . segmentIndexLock . RUnlock ( )
segIdx , ok := mt . buildID2SegmentIndex [ buildID ]
2022-09-15 15:44:31 +08:00
if ok && ! segIdx . IsDeleted {
2022-08-25 15:48:54 +08:00
return model . CloneSegmentIndex ( segIdx ) , true
2021-01-19 18:32:57 +08:00
}
2022-08-25 15:48:54 +08:00
return nil , false
2021-01-19 18:32:57 +08:00
}
2022-09-09 15:52:35 +08:00
func ( mt * metaTable ) GetTypeParams ( collID , indexID UniqueID ) [ ] * commonpb . KeyValuePair {
2022-08-25 15:48:54 +08:00
mt . indexLock . RLock ( )
defer mt . indexLock . RUnlock ( )
fieldIndexes , ok := mt . collectionIndexes [ collID ]
2021-04-16 15:37:13 +08:00
if ! ok {
2022-09-09 15:52:35 +08:00
return nil
2021-04-16 15:37:13 +08:00
}
2022-08-25 15:48:54 +08:00
index , ok := fieldIndexes [ indexID ]
if ! ok {
2022-09-09 15:52:35 +08:00
return nil
2021-10-28 18:20:27 +08:00
}
2022-08-25 15:48:54 +08:00
typeParams := make ( [ ] * commonpb . KeyValuePair , len ( index . TypeParams ) )
for i , param := range index . TypeParams {
typeParams [ i ] = proto . Clone ( param ) . ( * commonpb . KeyValuePair )
2021-05-27 22:24:29 +08:00
}
2022-08-25 15:48:54 +08:00
2022-09-09 15:52:35 +08:00
return typeParams
2022-07-07 14:44:21 +08:00
}
2021-05-27 22:24:29 +08:00
2022-08-25 15:48:54 +08:00
func ( mt * metaTable ) GetIndexParams ( collID , indexID UniqueID ) [ ] * commonpb . KeyValuePair {
mt . indexLock . RLock ( )
defer mt . indexLock . RUnlock ( )
2022-07-07 14:44:21 +08:00
2022-08-25 15:48:54 +08:00
fieldIndexes , ok := mt . collectionIndexes [ collID ]
if ! ok {
return nil
2022-07-07 14:44:21 +08:00
}
2022-08-25 15:48:54 +08:00
index , ok := fieldIndexes [ indexID ]
if ! ok {
return nil
}
indexParams := make ( [ ] * commonpb . KeyValuePair , len ( index . IndexParams ) )
for i , param := range index . IndexParams {
indexParams [ i ] = proto . Clone ( param ) . ( * commonpb . KeyValuePair )
}
return indexParams
}
2022-07-07 14:44:21 +08:00
2022-08-25 15:48:54 +08:00
func ( mt * metaTable ) CreateIndex ( index * model . Index ) error {
mt . indexLock . Lock ( )
defer mt . indexLock . Unlock ( )
log . Info ( "IndexCoord metaTable CreateIndex" , zap . Int64 ( "collectionID" , index . CollectionID ) ,
zap . Int64 ( "fieldID" , index . FieldID ) , zap . Int64 ( "indexID" , index . IndexID ) , zap . String ( "indexName" , index . IndexName ) )
if err := mt . saveFieldIndexMeta ( index ) ; err != nil {
log . Error ( "IndexCoord metaTable CreateIndex save meta fail" , zap . Int64 ( "collectionID" , index . CollectionID ) ,
zap . Int64 ( "fieldID" , index . FieldID ) , zap . Int64 ( "indexID" , index . IndexID ) ,
zap . String ( "indexName" , index . IndexName ) , zap . Error ( err ) )
2022-07-07 14:44:21 +08:00
return err
}
2022-08-25 15:48:54 +08:00
log . Info ( "IndexCoord metaTable CreateIndex success" , zap . Int64 ( "collectionID" , index . CollectionID ) ,
zap . Int64 ( "fieldID" , index . FieldID ) , zap . Int64 ( "indexID" , index . IndexID ) , zap . String ( "indexName" , index . IndexName ) )
2021-05-27 22:24:29 +08:00
return nil
2021-04-16 15:37:13 +08:00
}
2022-08-25 15:48:54 +08:00
// AddIndex adds the index meta corresponding the indexBuildID to meta table.
func ( mt * metaTable ) AddIndex ( segIndex * model . SegmentIndex ) error {
mt . segmentIndexLock . Lock ( )
defer mt . segmentIndexLock . Unlock ( )
buildID := segIndex . BuildID
log . Info ( "IndexCoord metaTable AddIndex" , zap . Int64 ( "collID" , segIndex . CollectionID ) ,
zap . Int64 ( "segID" , segIndex . SegmentID ) , zap . Int64 ( "indexID" , segIndex . IndexID ) ,
zap . Int64 ( "buildID" , buildID ) )
_ , ok := mt . buildID2SegmentIndex [ buildID ]
if ok {
log . Info ( "index already exists" , zap . Int64 ( "buildID" , buildID ) , zap . Int64 ( "indexID" , segIndex . IndexID ) )
return nil
2021-05-27 22:24:29 +08:00
}
2022-08-25 15:48:54 +08:00
segIndex . IndexState = commonpb . IndexState_Unissued
2021-02-23 11:57:18 +08:00
2022-09-28 11:02:54 +08:00
metrics . IndexCoordIndexTaskNum . WithLabelValues ( strconv . FormatInt ( segIndex . CollectionID , 10 ) , metrics . UnissuedIndexTaskLabel ) . Inc ( )
2022-08-25 15:48:54 +08:00
if err := mt . saveSegmentIndexMeta ( segIndex ) ; err != nil {
// no need to reload, no reason to compare version fail
log . Error ( "IndexCoord metaTable save index meta failed" , zap . Int64 ( "buildID" , buildID ) ,
zap . Int64 ( "indexID" , segIndex . IndexID ) , zap . Error ( err ) )
2022-07-07 14:44:21 +08:00
return err
}
2022-08-25 15:48:54 +08:00
log . Info ( "IndexCoord metaTable AddIndex success" , zap . Int64 ( "collID" , segIndex . CollectionID ) ,
zap . Int64 ( "segID" , segIndex . SegmentID ) , zap . Int64 ( "indexID" , segIndex . IndexID ) ,
zap . Int64 ( "buildID" , buildID ) )
2022-07-07 14:44:21 +08:00
return nil
}
2021-03-26 10:01:08 +08:00
2022-08-25 15:48:54 +08:00
func ( mt * metaTable ) NeedIndex ( collID , indexID UniqueID ) bool {
mt . indexLock . RLock ( )
defer mt . indexLock . RUnlock ( )
2021-05-27 22:24:29 +08:00
2022-08-25 15:48:54 +08:00
fieldIndexes , ok := mt . collectionIndexes [ collID ]
if ! ok {
return false
}
if index , ok := fieldIndexes [ indexID ] ; ! ok || index . IsDeleted {
return false
2022-07-07 14:44:21 +08:00
}
2021-05-27 22:24:29 +08:00
2022-08-25 15:48:54 +08:00
return true
2022-07-07 14:44:21 +08:00
}
2022-08-25 15:48:54 +08:00
func ( mt * metaTable ) canIndex ( segIdx * model . SegmentIndex ) bool {
if segIdx . IsDeleted {
log . Debug ( "Index has been deleted" , zap . Int64 ( "buildID" , segIdx . BuildID ) )
2022-07-07 14:44:21 +08:00
return false
2021-02-23 11:57:18 +08:00
}
2022-08-25 15:48:54 +08:00
if segIdx . NodeID != 0 {
2022-08-11 10:00:38 +08:00
log . Debug ( "IndexCoord metaTable BuildIndex, but indexMeta's NodeID is not zero" ,
2022-08-25 15:48:54 +08:00
zap . Int64 ( "buildID" , segIdx . BuildID ) , zap . Int64 ( "nodeID" , segIdx . NodeID ) )
2022-07-07 14:44:21 +08:00
return false
}
2022-08-25 15:48:54 +08:00
if segIdx . IndexState != commonpb . IndexState_Unissued {
2022-08-11 10:00:38 +08:00
log . Debug ( "IndexCoord metaTable BuildIndex, but indexMeta's state is not unissued" ,
2022-08-25 15:48:54 +08:00
zap . Int64 ( "buildID" , segIdx . BuildID ) , zap . String ( "state" , segIdx . IndexState . String ( ) ) )
2022-07-07 14:44:21 +08:00
return false
}
return true
}
// UpdateVersion updates the version and nodeID of the index meta, whenever the task is built once, the version will be updated once.
2022-08-25 15:48:54 +08:00
func ( mt * metaTable ) UpdateVersion ( buildID UniqueID , nodeID UniqueID ) error {
mt . segmentIndexLock . Lock ( )
defer mt . segmentIndexLock . Unlock ( )
log . Debug ( "IndexCoord metaTable UpdateVersion receive" , zap . Int64 ( "buildID" , buildID ) , zap . Int64 ( "nodeID" , nodeID ) )
segIdx , ok := mt . buildID2SegmentIndex [ buildID ]
if ! ok {
return fmt . Errorf ( "there is no index with buildID: %d" , buildID )
2022-07-07 14:44:21 +08:00
}
2022-08-25 15:48:54 +08:00
if ! mt . canIndex ( segIdx ) {
return fmt . Errorf ( "it's no necessary to build index with buildID = %d" , buildID )
}
updateFunc := func ( segIdx * model . SegmentIndex ) error {
segIdx . NodeID = nodeID
segIdx . IndexVersion ++
2022-09-05 17:37:11 +08:00
return mt . alterSegmentIndexes ( [ ] * model . SegmentIndex { segIdx } )
2022-08-25 15:48:54 +08:00
}
return mt . updateSegIndexMeta ( segIdx , updateFunc )
2021-02-23 11:57:18 +08:00
}
2022-07-07 14:44:21 +08:00
// BuildIndex set the index state to be InProgress. It means IndexNode is building the index.
2022-08-25 15:48:54 +08:00
func ( mt * metaTable ) BuildIndex ( buildID UniqueID ) error {
mt . segmentIndexLock . Lock ( )
defer mt . segmentIndexLock . Unlock ( )
segIdx , ok := mt . buildID2SegmentIndex [ buildID ]
if ! ok {
return fmt . Errorf ( "there is no index with buildID: %d" , buildID )
}
2022-07-07 14:44:21 +08:00
2022-08-25 15:48:54 +08:00
updateFunc := func ( segIdx * model . SegmentIndex ) error {
if segIdx . IsDeleted {
errMsg := fmt . Sprintf ( "index has been marked deleted, no need to build index with ID: %d" , segIdx . BuildID )
log . Warn ( errMsg , zap . Int64 ( "BuildID" , segIdx . BuildID ) )
return errors . New ( errMsg )
2022-07-07 14:44:21 +08:00
}
2022-08-25 15:48:54 +08:00
if segIdx . IndexState == commonpb . IndexState_Finished || segIdx . IndexState == commonpb . IndexState_Failed {
errMsg := fmt . Sprintf ( "index has been finished, no need to build index with ID: %d" , segIdx . BuildID )
log . Warn ( errMsg , zap . Int64 ( "BuildID" , segIdx . BuildID ) , zap . String ( "state" , segIdx . IndexState . String ( ) ) )
return errors . New ( errMsg )
2022-07-07 14:44:21 +08:00
}
2022-08-25 15:48:54 +08:00
segIdx . IndexState = commonpb . IndexState_InProgress
2022-07-07 14:44:21 +08:00
2022-09-23 09:58:51 +08:00
err := mt . alterSegmentIndexes ( [ ] * model . SegmentIndex { segIdx } )
2022-07-07 14:44:21 +08:00
if err != nil {
2022-08-25 15:48:54 +08:00
log . Error ( "IndexCoord metaTable BuildIndex fail" , zap . Int64 ( "buildID" , segIdx . BuildID ) , zap . Error ( err ) )
2022-07-07 14:44:21 +08:00
return err
}
return nil
}
2022-09-28 11:02:54 +08:00
if err := mt . updateSegIndexMeta ( segIdx , updateFunc ) ; err != nil {
return err
}
mt . updateIndexTasksMetrics ( )
return nil
2022-07-07 14:44:21 +08:00
}
2022-08-25 15:48:54 +08:00
// GetIndexesForCollection gets all indexes info with the specified collection.
func ( mt * metaTable ) GetIndexesForCollection ( collID UniqueID , indexName string ) [ ] * model . Index {
mt . indexLock . RLock ( )
defer mt . indexLock . RUnlock ( )
2022-07-07 14:44:21 +08:00
2022-08-25 15:48:54 +08:00
indexInfos := make ( [ ] * model . Index , 0 )
for _ , index := range mt . collectionIndexes [ collID ] {
if index . IsDeleted {
2022-07-07 14:44:21 +08:00
continue
}
2022-08-25 15:48:54 +08:00
if indexName == "" || indexName == index . IndexName {
indexInfos = append ( indexInfos , model . CloneIndex ( index ) )
2022-07-07 14:44:21 +08:00
}
}
2022-08-25 15:48:54 +08:00
return indexInfos
2022-07-07 14:44:21 +08:00
}
2022-10-25 16:59:30 +08:00
func ( mt * metaTable ) CanCreateIndex ( req * indexpb . CreateIndexRequest ) ( bool , error ) {
2022-08-25 15:48:54 +08:00
mt . indexLock . RLock ( )
defer mt . indexLock . RUnlock ( )
2022-07-07 14:44:21 +08:00
2022-08-25 15:48:54 +08:00
indexes , ok := mt . collectionIndexes [ req . CollectionID ]
if ! ok {
2022-10-25 16:59:30 +08:00
return true , nil
2022-07-07 14:44:21 +08:00
}
2022-08-25 15:48:54 +08:00
for _ , index := range indexes {
if index . IsDeleted {
continue
}
if req . IndexName == index . IndexName {
2022-10-25 16:59:30 +08:00
if mt . checkParams ( index , req ) {
return true , nil
}
2022-10-31 12:11:33 +08:00
errMsg := "at most one distinct index is allowed per field"
log . Warn ( errMsg ,
zap . String ( "source index" , fmt . Sprintf ( "{index_name: %s, field_id: %d, index_params: %v, type_params: %v}" , index . IndexName , index . FieldID , index . IndexParams , index . TypeParams ) ) ,
zap . String ( "current index" , fmt . Sprintf ( "{index_name: %s, field_id: %d, index_params: %v, type_params: %v}" , req . GetIndexName ( ) , req . GetFieldID ( ) , req . GetIndexParams ( ) , req . GetTypeParams ( ) ) ) )
2022-10-25 16:59:30 +08:00
return false , fmt . Errorf ( "CreateIndex failed: %s" , errMsg )
2022-08-25 15:48:54 +08:00
}
if req . FieldID == index . FieldID {
// creating multiple indexes on same field is not supported
2022-10-25 16:59:30 +08:00
return false , fmt . Errorf ( "CreateIndex failed: creating multiple indexes on same field is not supported" )
2021-05-27 22:24:29 +08:00
}
2021-01-19 18:32:57 +08:00
}
2022-10-25 16:59:30 +08:00
return true , nil
2021-01-19 18:32:57 +08:00
}
2022-08-25 15:48:54 +08:00
func ( mt * metaTable ) checkParams ( fieldIndex * model . Index , req * indexpb . CreateIndexRequest ) bool {
if fieldIndex . IndexName != req . IndexName {
return false
}
if fieldIndex . FieldID != req . FieldID {
return false
}
if len ( fieldIndex . TypeParams ) != len ( req . TypeParams ) {
return false
}
notEq := false
for _ , param1 := range fieldIndex . TypeParams {
exist := false
for _ , param2 := range req . TypeParams {
if param2 . Key == param1 . Key && param2 . Value == param1 . Value {
exist = true
}
2022-07-07 14:44:21 +08:00
}
2022-08-25 15:48:54 +08:00
if ! exist {
notEq = true
break
}
}
if notEq {
return false
}
if len ( fieldIndex . IndexParams ) != len ( req . IndexParams ) {
return false
}
for _ , param1 := range fieldIndex . IndexParams {
exist := false
for _ , param2 := range req . IndexParams {
if param2 . Key == param1 . Key && param2 . Value == param1 . Value {
exist = true
}
}
if ! exist {
notEq = true
break
2022-06-17 18:08:12 +08:00
}
}
2022-06-28 12:08:17 +08:00
2022-08-25 15:48:54 +08:00
return ! notEq
2022-06-17 18:08:12 +08:00
}
2022-08-25 15:48:54 +08:00
// HasSameReq determine whether there are same indexing tasks.
func ( mt * metaTable ) HasSameReq ( req * indexpb . CreateIndexRequest ) ( bool , UniqueID ) {
mt . indexLock . RLock ( )
defer mt . indexLock . RUnlock ( )
for _ , fieldIndex := range mt . collectionIndexes [ req . CollectionID ] {
2022-09-01 17:18:57 +08:00
if fieldIndex . IsDeleted {
continue
}
2022-08-25 15:48:54 +08:00
if ! mt . checkParams ( fieldIndex , req ) {
continue
2021-06-30 14:32:19 +08:00
}
2022-08-25 15:48:54 +08:00
log . Debug ( "IndexCoord has same index" , zap . Int64 ( "collectionID" , req . CollectionID ) ,
zap . Int64 ( "fieldID" , req . FieldID ) , zap . String ( "indexName" , req . IndexName ) ,
zap . Int64 ( "indexID" , fieldIndex . IndexID ) )
return true , fieldIndex . IndexID
2021-02-23 11:57:18 +08:00
}
2022-08-25 15:48:54 +08:00
return false , 0
2021-01-19 18:32:57 +08:00
}
2022-08-25 15:48:54 +08:00
func ( mt * metaTable ) HasSameIndex ( segmentID , indexID UniqueID ) ( bool , UniqueID ) {
mt . segmentIndexLock . RLock ( )
defer mt . segmentIndexLock . RUnlock ( )
if _ , ok := mt . segmentIndexes [ segmentID ] ; ! ok {
return false , 0
2021-01-19 18:32:57 +08:00
}
2022-08-25 15:48:54 +08:00
if index , ok := mt . segmentIndexes [ segmentID ] [ indexID ] ; ok {
return true , index . BuildID
2022-05-17 20:41:56 +08:00
}
2022-08-25 15:48:54 +08:00
return false , 0
}
func ( mt * metaTable ) GetIndexIDByName ( collID int64 , indexName string ) map [ int64 ] uint64 {
mt . indexLock . RLock ( )
defer mt . indexLock . RUnlock ( )
indexID2CreateTs := make ( map [ int64 ] uint64 )
fieldIndexes , ok := mt . collectionIndexes [ collID ]
if ! ok {
return indexID2CreateTs
2021-02-23 11:57:18 +08:00
}
2021-12-23 21:38:34 +08:00
2022-08-25 15:48:54 +08:00
for _ , index := range fieldIndexes {
if ! index . IsDeleted && ( indexName == "" || index . IndexName == indexName ) {
indexID2CreateTs [ index . IndexID ] = index . CreateTime
}
}
return indexID2CreateTs
2021-01-19 18:32:57 +08:00
}
2022-08-25 15:48:54 +08:00
func ( mt * metaTable ) GetFieldIDByIndexID ( collID , indexID UniqueID ) UniqueID {
mt . indexLock . RLock ( )
defer mt . indexLock . RUnlock ( )
2021-02-23 11:57:18 +08:00
2022-08-25 15:48:54 +08:00
if fieldIndexes , ok := mt . collectionIndexes [ collID ] ; ok {
if index , ok := fieldIndexes [ indexID ] ; ok {
return index . FieldID
}
2021-12-23 21:40:25 +08:00
}
2022-08-25 15:48:54 +08:00
return 0
2021-02-23 11:57:18 +08:00
}
2022-08-25 15:48:54 +08:00
func ( mt * metaTable ) GetIndexNameByID ( collID , indexID UniqueID ) string {
mt . indexLock . RLock ( )
defer mt . indexLock . RUnlock ( )
if fieldIndexes , ok := mt . collectionIndexes [ collID ] ; ok {
if index , ok := fieldIndexes [ indexID ] ; ok {
return index . IndexName
}
}
return ""
}
2021-05-27 22:24:29 +08:00
2022-08-25 15:48:54 +08:00
type IndexState struct {
state commonpb . IndexState
failReason string
}
2021-05-27 22:24:29 +08:00
2022-09-30 10:56:54 +08:00
type IndexStateCnt struct {
None int
Unissued int
InProgress int
Finished int
Failed int
FailReason string
}
2022-08-25 15:48:54 +08:00
// GetIndexStates gets the index states for indexID from meta table.
2022-09-30 10:56:54 +08:00
func ( mt * metaTable ) GetIndexStates ( indexID int64 , createTs uint64 ) ( [ ] * IndexState , IndexStateCnt ) {
2022-08-25 15:48:54 +08:00
mt . segmentIndexLock . RLock ( )
defer mt . segmentIndexLock . RUnlock ( )
segIndexStates := make ( [ ] * IndexState , 0 )
var (
cntNone = 0
cntUnissued = 0
cntInProgress = 0
cntFinished = 0
cntFailed = 0
2022-09-30 10:56:54 +08:00
failReason string
2022-08-25 15:48:54 +08:00
)
for _ , indexID2SegIdx := range mt . segmentIndexes {
segIdx , ok := indexID2SegIdx [ indexID ]
if ! ok {
continue
}
if segIdx . CreateTime > createTs {
continue
}
if segIdx . IsDeleted {
// skip deleted index, deleted by compaction
continue
}
switch segIdx . IndexState {
case commonpb . IndexState_IndexStateNone :
cntNone ++
case commonpb . IndexState_Unissued :
cntUnissued ++
case commonpb . IndexState_InProgress :
cntInProgress ++
case commonpb . IndexState_Finished :
cntFinished ++
case commonpb . IndexState_Failed :
cntFailed ++
2022-09-30 10:56:54 +08:00
failReason += fmt . Sprintf ( "%d: %s;" , segIdx . SegmentID , segIdx . FailReason )
2022-08-25 15:48:54 +08:00
}
segIndexStates = append ( segIndexStates , & IndexState {
state : segIdx . IndexState ,
failReason : segIdx . FailReason ,
} )
2021-05-27 22:24:29 +08:00
}
2022-08-25 15:48:54 +08:00
log . Debug ( "IndexCoord get index states success" , zap . Int64 ( "indexID" , indexID ) ,
zap . Int ( "total" , len ( segIndexStates ) ) , zap . Int ( "None" , cntNone ) , zap . Int ( "Unissued" , cntUnissued ) ,
zap . Int ( "InProgress" , cntInProgress ) , zap . Int ( "Finished" , cntFinished ) , zap . Int ( "Failed" , cntFailed ) )
2022-09-30 10:56:54 +08:00
return segIndexStates , IndexStateCnt {
None : cntNone ,
Unissued : cntNone ,
InProgress : cntInProgress ,
Finished : cntFinished ,
Failed : cntFailed ,
FailReason : failReason ,
}
2022-06-23 10:40:13 +08:00
}
2022-08-25 15:48:54 +08:00
func ( mt * metaTable ) GetSegmentIndexes ( segID UniqueID ) [ ] * model . SegmentIndex {
mt . segmentIndexLock . RLock ( )
defer mt . segmentIndexLock . RUnlock ( )
2021-07-14 14:15:55 +08:00
2022-08-25 15:48:54 +08:00
segIndexInfos := make ( [ ] * model . SegmentIndex , 0 )
if segIndexes , ok := mt . segmentIndexes [ segID ] ; ok {
for _ , segIdx := range segIndexes {
2022-09-15 15:44:31 +08:00
if segIdx . IsDeleted {
continue
}
2022-08-25 15:48:54 +08:00
segIndexInfos = append ( segIndexInfos , model . CloneSegmentIndex ( segIdx ) )
2021-05-27 22:24:29 +08:00
}
}
2022-08-25 15:48:54 +08:00
return segIndexInfos
2021-05-27 22:24:29 +08:00
}
2022-09-15 15:44:31 +08:00
func ( mt * metaTable ) GetSegmentIndexState ( segmentID UniqueID ) IndexState {
2022-08-25 15:48:54 +08:00
mt . segmentIndexLock . RLock ( )
defer mt . segmentIndexLock . RUnlock ( )
2021-05-27 22:24:29 +08:00
2022-09-15 15:44:31 +08:00
state := IndexState {
state : commonpb . IndexState_Finished ,
failReason : "" ,
}
2022-08-25 15:48:54 +08:00
if segIdxes , ok := mt . segmentIndexes [ segmentID ] ; ok {
2022-09-15 15:44:31 +08:00
for _ , segIdx := range segIdxes {
if segIdx . IsDeleted {
continue
}
if segIdx . IndexState != commonpb . IndexState_Finished {
state . state = segIdx . IndexState
state . failReason = segIdx . FailReason
2022-08-25 15:48:54 +08:00
}
2022-05-31 16:36:03 +08:00
}
2022-08-25 15:48:54 +08:00
}
2022-09-15 15:44:31 +08:00
return state
2022-08-25 15:48:54 +08:00
}
// GetIndexBuildProgress gets the index progress for indexID from meta table.
2022-11-14 14:37:07 +08:00
func ( mt * metaTable ) GetIndexBuildProgress ( indexID int64 , segIDs [ ] UniqueID ) int64 {
2022-08-25 15:48:54 +08:00
mt . segmentIndexLock . RLock ( )
defer mt . segmentIndexLock . RUnlock ( )
indexRows := int64 ( 0 )
2022-11-14 14:37:07 +08:00
for _ , segID := range segIDs {
segIndexes , ok := mt . segmentIndexes [ segID ]
2022-08-25 15:48:54 +08:00
if ! ok {
2021-06-24 14:36:08 +08:00
continue
}
2022-11-14 14:37:07 +08:00
if segIdx , ok2 := segIndexes [ indexID ] ; ok2 {
if segIdx . IsDeleted {
// partition is dropped, but DataCoord has not received the message
continue
}
// flat index, small segment
if segIdx . IndexState == commonpb . IndexState_Finished {
indexRows += segIdx . NumRows
}
2021-06-24 14:36:08 +08:00
}
2022-08-25 15:48:54 +08:00
}
log . Debug ( "IndexCoord get index states success" , zap . Int64 ( "indexID" , indexID ) ,
zap . Int64 ( "indexRows" , indexRows ) )
return indexRows
}
// MarkIndexAsDeleted will mark the corresponding index as deleted, and recycleUnusedIndexFiles will recycle these tasks.
func ( mt * metaTable ) MarkIndexAsDeleted ( collID UniqueID , indexIDs [ ] UniqueID ) error {
log . Info ( "IndexCoord metaTable MarkIndexAsDeleted" , zap . Int64 ( "collID" , collID ) ,
zap . Int64s ( "indexIDs" , indexIDs ) )
mt . indexLock . Lock ( )
defer mt . indexLock . Unlock ( )
fieldIndexes , ok := mt . collectionIndexes [ collID ]
if ! ok {
return nil
}
indexes := make ( [ ] * model . Index , 0 )
for _ , indexID := range indexIDs {
index , ok := fieldIndexes [ indexID ]
2022-09-23 09:36:51 +08:00
if ! ok || index . IsDeleted {
2021-06-24 14:36:08 +08:00
continue
}
2022-08-25 15:48:54 +08:00
clonedIndex := model . CloneIndex ( index )
clonedIndex . IsDeleted = true
indexes = append ( indexes , clonedIndex )
}
2022-09-23 09:36:51 +08:00
if len ( indexes ) == 0 {
return nil
}
2022-08-25 15:48:54 +08:00
err := mt . alterIndexes ( indexes )
if err != nil {
log . Error ( "IndexCoord metaTable MarkIndexAsDeleted fail" , zap . Int64 ( "collID" , collID ) ,
zap . Int64s ( "indexIDs" , indexIDs ) , zap . Error ( err ) )
return err
}
log . Info ( "IndexCoord metaTable MarkIndexAsDeleted success" , zap . Int64 ( "collID" , collID ) , zap . Int64s ( "indexIDs" , indexIDs ) )
return nil
}
2022-08-31 10:23:04 +08:00
// MarkSegmentsIndexAsDeleted will mark the index on the segment corresponding the buildID as deleted, and recycleUnusedSegIndexes will recycle these tasks.
2022-09-23 09:36:51 +08:00
func ( mt * metaTable ) MarkSegmentsIndexAsDeleted ( selector func ( index * model . SegmentIndex ) bool ) error {
2022-08-25 15:48:54 +08:00
mt . segmentIndexLock . Lock ( )
defer mt . segmentIndexLock . Unlock ( )
buildIDs := make ( [ ] UniqueID , 0 )
segIdxes := make ( [ ] * model . SegmentIndex , 0 )
2022-09-23 09:36:51 +08:00
for _ , segIdx := range mt . buildID2SegmentIndex {
if segIdx . IsDeleted {
continue
}
if selector ( segIdx ) {
clonedSegIdx := model . CloneSegmentIndex ( segIdx )
clonedSegIdx . IsDeleted = true
segIdxes = append ( segIdxes , clonedSegIdx )
buildIDs = append ( buildIDs , segIdx . BuildID )
2021-05-27 22:24:29 +08:00
}
2022-08-25 15:48:54 +08:00
}
2022-09-23 09:36:51 +08:00
2022-08-25 15:48:54 +08:00
if len ( segIdxes ) == 0 {
2022-09-23 09:36:51 +08:00
log . Debug ( "IndexCoord metaTable MarkSegmentsIndexAsDeleted success, no segment index need to mark" )
2022-08-25 15:48:54 +08:00
return nil
}
err := mt . alterSegmentIndexes ( segIdxes )
if err != nil {
return err
}
return nil
}
2022-10-19 16:55:27 +08:00
func ( mt * metaTable ) GetSegmentIndexByBuildID ( buildID UniqueID ) ( bool , * model . SegmentIndex ) {
2022-08-25 15:48:54 +08:00
mt . segmentIndexLock . RLock ( )
defer mt . segmentIndexLock . RUnlock ( )
log . Debug ( "IndexCoord get index file path from meta table" , zap . Int64 ( "buildID" , buildID ) )
segIdx , ok := mt . buildID2SegmentIndex [ buildID ]
if ! ok || segIdx . IsDeleted {
2022-10-19 16:55:27 +08:00
return false , nil
2022-08-25 15:48:54 +08:00
}
if segIdx . IndexState != commonpb . IndexState_Finished && segIdx . IndexState != commonpb . IndexState_Failed {
2022-10-19 16:55:27 +08:00
return false , nil
2022-08-25 15:48:54 +08:00
}
2022-10-19 16:55:27 +08:00
log . Debug ( "IndexCoord get segment index file path success" , zap . Int64 ( "buildID" , buildID ) ,
zap . Int ( "index files num" , len ( segIdx . IndexFileKeys ) ) )
return true , segIdx
2022-08-25 15:48:54 +08:00
}
func ( mt * metaTable ) IsIndexDeleted ( collID , indexID UniqueID ) bool {
mt . indexLock . RLock ( )
defer mt . indexLock . RUnlock ( )
fieldIndexes , ok := mt . collectionIndexes [ collID ]
if ! ok {
return true
}
if index , ok := fieldIndexes [ indexID ] ; ! ok || index . IsDeleted {
return true
}
return false
}
func ( mt * metaTable ) IsSegIndexDeleted ( buildID UniqueID ) bool {
mt . segmentIndexLock . RLock ( )
defer mt . segmentIndexLock . RUnlock ( )
if segIdx , ok := mt . buildID2SegmentIndex [ buildID ] ; ! ok || segIdx . IsDeleted {
return true
}
return false
}
func ( mt * metaTable ) GetMetasByNodeID ( nodeID UniqueID ) [ ] * model . SegmentIndex {
mt . segmentIndexLock . RLock ( )
defer mt . segmentIndexLock . RUnlock ( )
metas := make ( [ ] * model . SegmentIndex , 0 )
for _ , meta := range mt . buildID2SegmentIndex {
if meta . IsDeleted {
2021-06-24 14:36:08 +08:00
continue
}
2022-08-25 15:48:54 +08:00
if nodeID == meta . NodeID {
metas = append ( metas , model . CloneSegmentIndex ( meta ) )
2021-06-24 14:36:08 +08:00
}
2022-08-25 15:48:54 +08:00
}
return metas
}
func ( mt * metaTable ) GetAllSegIndexes ( ) map [ int64 ] * model . SegmentIndex {
mt . segmentIndexLock . RLock ( )
defer mt . segmentIndexLock . RUnlock ( )
segIndexes := make ( map [ int64 ] * model . SegmentIndex )
for _ , meta := range mt . buildID2SegmentIndex {
segIndexes [ meta . SegmentID ] = model . CloneSegmentIndex ( meta )
}
return segIndexes
}
func ( mt * metaTable ) GetDeletedIndexes ( ) [ ] * model . Index {
mt . indexLock . RLock ( )
defer mt . indexLock . RUnlock ( )
var indexes [ ] * model . Index
for _ , fieldIndexes := range mt . collectionIndexes {
for _ , index := range fieldIndexes {
if index . IsDeleted {
indexes = append ( indexes , model . CloneIndex ( index ) )
2021-06-24 14:36:08 +08:00
}
}
2022-08-25 15:48:54 +08:00
}
return indexes
}
2022-09-15 15:44:31 +08:00
func ( mt * metaTable ) GetDeletedSegmentIndexes ( ) [ ] * model . SegmentIndex {
mt . segmentIndexLock . RLock ( )
defer mt . segmentIndexLock . RUnlock ( )
segIndexes := make ( [ ] * model . SegmentIndex , 0 )
for _ , segIdx := range mt . buildID2SegmentIndex {
if segIdx . IsDeleted {
segIndexes = append ( segIndexes , segIdx )
}
}
return segIndexes
}
2022-08-25 15:48:54 +08:00
func ( mt * metaTable ) GetBuildIDsFromIndexID ( indexID UniqueID ) [ ] UniqueID {
mt . segmentIndexLock . RLock ( )
defer mt . segmentIndexLock . RUnlock ( )
buildIDs := make ( [ ] UniqueID , 0 )
for buildID , segIdx := range mt . buildID2SegmentIndex {
if segIdx . IndexID == indexID {
buildIDs = append ( buildIDs , buildID )
2021-06-24 14:36:08 +08:00
}
2022-08-25 15:48:54 +08:00
}
return buildIDs
}
func ( mt * metaTable ) GetBuildIDsFromSegIDs ( segIDs [ ] UniqueID ) [ ] UniqueID {
mt . segmentIndexLock . RLock ( )
defer mt . segmentIndexLock . RUnlock ( )
buildIDs := make ( [ ] UniqueID , 0 )
for _ , segID := range segIDs {
if segIdxes , ok := mt . segmentIndexes [ segID ] ; ok {
for _ , segIdx := range segIdxes {
buildIDs = append ( buildIDs , segIdx . BuildID )
}
2022-07-07 14:44:21 +08:00
}
2021-05-27 22:24:29 +08:00
}
2022-08-25 15:48:54 +08:00
return buildIDs
}
2021-06-24 14:36:08 +08:00
2022-08-25 15:48:54 +08:00
// RemoveIndex remove the index on the collection from meta table.
func ( mt * metaTable ) RemoveIndex ( collID , indexID UniqueID ) error {
mt . indexLock . Lock ( )
defer mt . indexLock . Unlock ( )
2022-09-23 09:58:51 +08:00
log . Info ( "IndexCoord meta table remove index" , zap . Int64 ( "collID" , collID ) , zap . Int64 ( "indexID" , indexID ) )
2022-08-25 15:48:54 +08:00
err := mt . catalog . DropIndex ( context . Background ( ) , collID , indexID )
if err != nil {
2022-09-23 09:58:51 +08:00
log . Info ( "IndexCoord meta table remove index fail" , zap . Int64 ( "collID" , collID ) ,
zap . Int64 ( "indexID" , indexID ) , zap . Error ( err ) )
2022-08-25 15:48:54 +08:00
return err
}
delete ( mt . collectionIndexes [ collID ] , indexID )
2022-09-28 11:02:54 +08:00
if len ( mt . collectionIndexes [ collID ] ) == 0 {
delete ( mt . collectionIndexes , collID )
metrics . IndexCoordIndexTaskNum . Delete ( prometheus . Labels { "collection_id" : strconv . FormatInt ( collID , 10 ) , "index_task_status" : metrics . UnissuedIndexTaskLabel } )
metrics . IndexCoordIndexTaskNum . Delete ( prometheus . Labels { "collection_id" : strconv . FormatInt ( collID , 10 ) , "index_task_status" : metrics . InProgressIndexTaskLabel } )
metrics . IndexCoordIndexTaskNum . Delete ( prometheus . Labels { "collection_id" : strconv . FormatInt ( collID , 10 ) , "index_task_status" : metrics . FinishedIndexTaskLabel } )
metrics . IndexCoordIndexTaskNum . Delete ( prometheus . Labels { "collection_id" : strconv . FormatInt ( collID , 10 ) , "index_task_status" : metrics . FailedIndexTaskLabel } )
}
2022-09-23 09:58:51 +08:00
log . Info ( "IndexCoord meta table remove index success" , zap . Int64 ( "collID" , collID ) , zap . Int64 ( "indexID" , indexID ) )
2022-08-25 15:48:54 +08:00
return nil
2021-05-27 22:24:29 +08:00
}
2022-08-25 15:48:54 +08:00
// RemoveSegmentIndex remove the index on the segment from meta table.
func ( mt * metaTable ) RemoveSegmentIndex ( collID , partID , segID , buildID UniqueID ) error {
mt . segmentIndexLock . Lock ( )
defer mt . segmentIndexLock . Unlock ( )
2021-05-27 22:24:29 +08:00
2022-08-25 15:48:54 +08:00
err := mt . catalog . DropSegmentIndex ( context . Background ( ) , collID , partID , segID , buildID )
if err != nil {
return err
2021-05-27 22:24:29 +08:00
}
2022-08-25 15:48:54 +08:00
segIdx , ok := mt . buildID2SegmentIndex [ buildID ]
if ! ok {
return nil
2021-05-27 22:24:29 +08:00
}
2022-09-28 11:02:54 +08:00
delete ( mt . segmentIndexes [ segID ] , segIdx . IndexID )
2022-08-25 15:48:54 +08:00
delete ( mt . buildID2SegmentIndex , buildID )
2022-09-28 11:02:54 +08:00
if len ( mt . segmentIndexes [ segID ] ) == 0 {
delete ( mt . segmentIndexes , segID )
}
2022-08-25 15:48:54 +08:00
return nil
2021-01-19 18:32:57 +08:00
}
2021-09-14 10:41:21 +08:00
2022-08-25 15:48:54 +08:00
// HasBuildID checks if there is an index corresponding the buildID in the meta table.
2022-07-08 16:54:22 +08:00
func ( mt * metaTable ) HasBuildID ( buildID UniqueID ) bool {
2022-08-25 15:48:54 +08:00
mt . segmentIndexLock . RLock ( )
defer mt . segmentIndexLock . RUnlock ( )
2021-09-14 10:41:21 +08:00
2022-08-25 15:48:54 +08:00
_ , ok := mt . buildID2SegmentIndex [ buildID ]
2022-07-08 16:54:22 +08:00
return ok
2021-09-14 10:41:21 +08:00
}
2022-08-25 15:48:54 +08:00
// ResetNodeID resets the nodeID of the index meta corresponding the buildID.
func ( mt * metaTable ) ResetNodeID ( buildID UniqueID ) error {
mt . segmentIndexLock . Lock ( )
defer mt . segmentIndexLock . Unlock ( )
2022-09-05 17:37:11 +08:00
updateFunc := func ( segIdx * model . SegmentIndex ) error {
segIdx . NodeID = 0
return mt . alterSegmentIndexes ( [ ] * model . SegmentIndex { segIdx } )
2022-08-25 15:48:54 +08:00
}
segIdx , ok := mt . buildID2SegmentIndex [ buildID ]
if ! ok {
return fmt . Errorf ( "there is no index with buildID: %d" , buildID )
}
return mt . updateSegIndexMeta ( segIdx , updateFunc )
}
// ResetMeta resets the nodeID and index state of the index meta corresponding the buildID.
func ( mt * metaTable ) ResetMeta ( buildID UniqueID ) error {
mt . segmentIndexLock . Lock ( )
defer mt . segmentIndexLock . Unlock ( )
segIdx , ok := mt . buildID2SegmentIndex [ buildID ]
if ! ok {
return fmt . Errorf ( "there is no index with buildID: %d" , buildID )
}
2022-09-05 17:37:11 +08:00
updateFunc := func ( segIdx * model . SegmentIndex ) error {
segIdx . NodeID = 0
2022-08-25 15:48:54 +08:00
segIdx . IndexState = commonpb . IndexState_Unissued
2022-09-05 17:37:11 +08:00
return mt . alterSegmentIndexes ( [ ] * model . SegmentIndex { segIdx } )
2022-08-25 15:48:54 +08:00
}
2022-09-28 11:02:54 +08:00
if err := mt . updateSegIndexMeta ( segIdx , updateFunc ) ; err != nil {
return err
}
mt . updateIndexTasksMetrics ( )
return nil
2022-08-25 15:48:54 +08:00
}
2022-09-05 17:37:11 +08:00
func ( mt * metaTable ) FinishTask ( taskInfo * indexpb . IndexTaskInfo ) error {
2022-08-25 15:48:54 +08:00
mt . segmentIndexLock . Lock ( )
defer mt . segmentIndexLock . Unlock ( )
2022-09-05 17:37:11 +08:00
segIdx , ok := mt . buildID2SegmentIndex [ taskInfo . BuildID ]
2022-08-25 15:48:54 +08:00
if ! ok || segIdx . IsDeleted {
2022-09-05 17:37:11 +08:00
return fmt . Errorf ( "there is no index with buildID: %d" , taskInfo . BuildID )
2022-08-25 15:48:54 +08:00
}
updateFunc := func ( segIdx * model . SegmentIndex ) error {
2022-09-05 17:37:11 +08:00
segIdx . IndexState = taskInfo . State
2022-10-19 16:55:27 +08:00
segIdx . IndexFileKeys = common . CloneStringList ( taskInfo . IndexFileKeys )
2022-09-05 17:37:11 +08:00
segIdx . FailReason = taskInfo . FailReason
segIdx . IndexSize = taskInfo . SerializedSize
return mt . alterSegmentIndexes ( [ ] * model . SegmentIndex { segIdx } )
2022-08-25 15:48:54 +08:00
}
2022-09-28 11:02:54 +08:00
if err := mt . updateSegIndexMeta ( segIdx , updateFunc ) ; err != nil {
return err
}
mt . updateIndexTasksMetrics ( )
2022-11-16 14:23:09 +08:00
log . Info ( "finish index task success" , zap . Int64 ( "buildID" , taskInfo . BuildID ) ,
zap . String ( "state" , taskInfo . GetState ( ) . String ( ) ) , zap . String ( "fail reason" , taskInfo . GetFailReason ( ) ) )
2022-09-28 11:02:54 +08:00
return nil
2022-08-25 15:48:54 +08:00
}
2022-09-15 15:44:31 +08:00
func ( mt * metaTable ) MarkSegmentsIndexAsDeletedByBuildID ( buildIDs [ ] UniqueID ) error {
mt . segmentIndexLock . Lock ( )
defer mt . segmentIndexLock . Unlock ( )
segIdxes := make ( [ ] * model . SegmentIndex , 0 )
for _ , buildID := range buildIDs {
if segIdx , ok := mt . buildID2SegmentIndex [ buildID ] ; ok {
if segIdx . IsDeleted {
continue
}
clonedSegIdx := model . CloneSegmentIndex ( segIdx )
clonedSegIdx . IsDeleted = true
segIdxes = append ( segIdxes , clonedSegIdx )
}
}
if len ( segIdxes ) == 0 {
log . Debug ( "IndexCoord metaTable MarkSegmentsIndexAsDeletedByBuildID success, already have deleted" ,
zap . Int64s ( "buildIDs" , buildIDs ) )
return nil
}
err := mt . alterSegmentIndexes ( segIdxes )
if err != nil {
log . Error ( "IndexCoord metaTable MarkSegmentsIndexAsDeletedByBuildID fail" , zap . Int64s ( "buildIDs" , buildIDs ) , zap . Error ( err ) )
return err
}
log . Info ( "IndexCoord metaTable MarkSegmentsIndexAsDeletedByBuildID success" , zap . Int64s ( "buildIDs" , buildIDs ) )
return nil
}
2022-09-21 16:34:51 +08:00
func ( mt * metaTable ) MarkSegmentWriteHandoff ( segID UniqueID ) error {
mt . segmentIndexLock . Lock ( )
defer mt . segmentIndexLock . Unlock ( )
segIdxes := make ( [ ] * model . SegmentIndex , 0 )
if segIndexes , ok := mt . segmentIndexes [ segID ] ; ok {
for _ , segIdx := range segIndexes {
clonedSegIdx := model . CloneSegmentIndex ( segIdx )
clonedSegIdx . WriteHandoff = true
segIdxes = append ( segIdxes , clonedSegIdx )
}
}
return mt . alterSegmentIndexes ( segIdxes )
}
2022-10-27 20:25:35 +08:00
func ( mt * metaTable ) AlreadyWrittenHandoff ( segID UniqueID ) bool {
mt . segmentIndexLock . RLock ( )
defer mt . segmentIndexLock . RUnlock ( )
if segIndexes , ok := mt . segmentIndexes [ segID ] ; ok {
for _ , segIdx := range segIndexes {
if ! segIdx . WriteHandoff {
return false
}
}
}
return true
}