2021-12-16 10:07:10 +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-04-19 11:12:56 +08:00
// with the License. You may obtain a copy of the License at
//
2021-12-16 10:07:10 +08:00
// http://www.apache.org/licenses/LICENSE-2.0
2021-04-19 11:12:56 +08:00
//
2021-12-16 10:07:10 +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-04-19 11:12:56 +08:00
2021-06-18 21:30:08 +08:00
package rootcoord
2021-01-19 14:44:03 +08:00
import (
2022-07-22 10:20:29 +08:00
"context"
2022-08-24 10:02:52 +08:00
"errors"
2021-03-05 10:15:27 +08:00
"fmt"
2021-01-19 14:44:03 +08:00
"sync"
2022-07-22 10:20:29 +08:00
"github.com/milvus-io/milvus/internal/common"
2021-04-22 14:45:57 +08:00
"github.com/milvus-io/milvus/internal/log"
2022-07-22 10:20:29 +08:00
"github.com/milvus-io/milvus/internal/metastore"
2022-08-20 10:24:51 +08:00
"github.com/milvus-io/milvus/internal/metastore/kv/rootcoord"
2022-07-22 10:20:29 +08:00
"github.com/milvus-io/milvus/internal/metastore/model"
2021-04-22 14:45:57 +08:00
"github.com/milvus-io/milvus/internal/proto/commonpb"
2022-04-11 19:49:34 +08:00
"github.com/milvus-io/milvus/internal/proto/internalpb"
"github.com/milvus-io/milvus/internal/proto/milvuspb"
2021-04-22 14:45:57 +08:00
"github.com/milvus-io/milvus/internal/proto/schemapb"
2022-08-11 12:12:38 +08:00
"github.com/milvus-io/milvus/internal/util/contextutil"
"github.com/milvus-io/milvus/internal/util/funcutil"
2021-05-14 21:26:06 +08:00
"github.com/milvus-io/milvus/internal/util/typeutil"
2022-07-22 10:20:29 +08:00
"go.uber.org/zap"
2021-01-19 14:44:03 +08:00
)
2021-01-20 09:36:50 +08:00
const (
2021-09-23 15:10:00 +08:00
// TimestampPrefix prefix for timestamp
2022-08-20 10:24:51 +08:00
TimestampPrefix = rootcoord . ComponentPrefix + "/timestamp"
2021-05-18 14:18:02 +08:00
2021-09-23 15:10:00 +08:00
// DDOperationPrefix prefix for DD operation
2022-08-20 10:24:51 +08:00
DDOperationPrefix = rootcoord . ComponentPrefix + "/dd-operation"
2021-05-12 15:33:53 +08:00
2021-09-23 15:10:00 +08:00
// DDMsgSendPrefix prefix to indicate whether DD msg has been send
2022-08-20 10:24:51 +08:00
DDMsgSendPrefix = rootcoord . ComponentPrefix + "/dd-msg-send"
2021-09-23 15:10:00 +08:00
// CreateCollectionDDType name of DD type for create collection
2021-05-14 21:26:06 +08:00
CreateCollectionDDType = "CreateCollection"
2021-09-23 15:10:00 +08:00
// 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"
2022-04-11 19:49:34 +08:00
2022-04-29 13:35:49 +08:00
// DefaultIndexType name of default index type for scalar field
DefaultIndexType = "STL_SORT"
// DefaultStringIndexType name of default index type for varChar/string field
DefaultStringIndexType = "Trie"
2021-01-20 09:36:50 +08:00
)
2022-05-05 21:17:50 +08:00
// MetaTable store all rootCoord meta info
2021-09-23 15:10:00 +08:00
type MetaTable struct {
2022-08-11 12:12:38 +08:00
ctx context . Context
2022-08-20 10:24:51 +08:00
catalog metastore . RootCoordCatalog
2022-07-22 10:20:29 +08:00
collID2Meta map [ typeutil . UniqueID ] model . Collection // collection id -> collection meta
collName2ID map [ string ] typeutil . UniqueID // collection name to collection id
collAlias2ID map [ string ] typeutil . UniqueID // collection alias to collection id
partID2IndexedSegID map [ typeutil . UniqueID ] map [ typeutil . UniqueID ] bool // partition id -> segment_id -> bool
segID2IndexID map [ typeutil . UniqueID ] typeutil . UniqueID // segment_id -> index_id
indexID2Meta map [ typeutil . UniqueID ] * model . Index // collection id/index_id -> meta
2021-01-19 14:44:03 +08:00
2022-08-24 10:02:52 +08:00
ddLock sync . RWMutex
permissionLock sync . RWMutex
2021-01-19 14:44:03 +08:00
}
2021-12-28 19:24:17 +08:00
// NewMetaTable creates meta table for rootcoord, which stores all in-memory information
2021-10-20 16:44:49 +08:00
// for collection, partition, segment, index etc.
2022-08-20 10:24:51 +08:00
func NewMetaTable ( ctx context . Context , catalog metastore . RootCoordCatalog ) ( * MetaTable , error ) {
2021-09-23 15:10:00 +08:00
mt := & MetaTable {
2022-08-11 12:12:38 +08:00
ctx : contextutil . WithTenantID ( ctx , Params . CommonCfg . ClusterName ) ,
catalog : catalog ,
ddLock : sync . RWMutex { } ,
2021-01-19 14:44:03 +08:00
}
2022-07-22 10:20:29 +08:00
err := mt . reloadFromCatalog ( )
2021-01-19 14:44:03 +08:00
if err != nil {
return nil , err
}
return mt , nil
}
2022-07-22 10:20:29 +08:00
func ( mt * MetaTable ) reloadFromCatalog ( ) error {
mt . collID2Meta = make ( map [ typeutil . UniqueID ] model . Collection )
2021-01-19 14:44:03 +08:00
mt . collName2ID = make ( map [ string ] typeutil . UniqueID )
2021-09-18 11:13:51 +08:00
mt . collAlias2ID = make ( map [ string ] typeutil . UniqueID )
2022-07-22 10:20:29 +08:00
mt . partID2IndexedSegID = make ( map [ typeutil . UniqueID ] map [ typeutil . UniqueID ] bool )
mt . segID2IndexID = make ( map [ typeutil . UniqueID ] typeutil . UniqueID )
mt . indexID2Meta = make ( map [ typeutil . UniqueID ] * model . Index )
2021-01-19 14:44:03 +08:00
2022-08-10 10:22:38 +08:00
collAliases , err := mt . catalog . ListAliases ( mt . ctx , 0 )
2022-06-15 19:14:10 +08:00
if err != nil {
return err
}
2022-07-22 10:20:29 +08:00
for _ , aliasInfo := range collAliases {
mt . collAlias2ID [ aliasInfo . Name ] = aliasInfo . CollectionID
2022-06-15 19:14:10 +08:00
}
2022-07-22 10:20:29 +08:00
collMap , err := mt . catalog . ListCollections ( mt . ctx , 0 )
2021-01-19 14:44:03 +08:00
if err != nil {
return err
}
2022-07-22 10:20:29 +08:00
for _ , coll := range collMap {
if _ , ok := mt . collAlias2ID [ coll . Name ] ; ok {
2022-06-15 19:14:10 +08:00
continue
}
2022-07-22 10:20:29 +08:00
mt . collID2Meta [ coll . CollectionID ] = * coll
mt . collName2ID [ coll . Name ] = coll . CollectionID
2022-06-10 13:10:08 +08:00
}
2022-07-22 10:20:29 +08:00
indexes , err := mt . catalog . ListIndexes ( mt . ctx )
2022-06-10 13:10:08 +08:00
if err != nil {
return err
}
2022-07-22 10:20:29 +08:00
for _ , index := range indexes {
for _ , segIndexInfo := range index . SegmentIndexes {
// update partID2IndexedSegID
segIDMap , ok := mt . partID2IndexedSegID [ segIndexInfo . Segment . PartitionID ]
if ok {
segIDMap [ segIndexInfo . Segment . SegmentID ] = true
} else {
idMap := make ( map [ typeutil . UniqueID ] bool )
idMap [ segIndexInfo . Segment . SegmentID ] = true
mt . partID2IndexedSegID [ segIndexInfo . Segment . PartitionID ] = idMap
}
2022-06-10 13:10:08 +08:00
2022-07-22 10:20:29 +08:00
mt . segID2IndexID [ segIndexInfo . Segment . SegmentID ] = index . IndexID
2021-01-19 14:44:03 +08:00
}
2022-07-22 10:20:29 +08:00
mt . indexID2Meta [ index . IndexID ] = index
2021-01-19 14:44:03 +08:00
}
2021-09-18 09:13:50 +08:00
log . Debug ( "reload meta table from KV successfully" )
2021-01-20 09:36:50 +08:00
return nil
2021-01-19 14:44:03 +08:00
}
2021-09-23 15:10:00 +08:00
// AddCollection add collection
2022-07-22 10:20:29 +08:00
func ( mt * MetaTable ) AddCollection ( coll * model . Collection , ts typeutil . Timestamp , ddOpStr string ) error {
2021-01-19 14:44:03 +08:00
mt . ddLock . Lock ( )
defer mt . ddLock . Unlock ( )
2021-01-20 09:36:50 +08:00
2022-07-22 10:20:29 +08:00
if _ , ok := mt . collName2ID [ coll . Name ] ; ok {
return fmt . Errorf ( "collection %s exist" , coll . Name )
2021-02-11 08:41:59 +08:00
}
2021-01-20 09:36:50 +08:00
2022-06-07 12:00:07 +08:00
coll . CreateTime = ts
2022-07-22 10:20:29 +08:00
for _ , partition := range coll . Partitions {
partition . PartitionCreatedTimestamp = ts
2022-06-10 13:10:08 +08:00
}
2022-07-22 10:20:29 +08:00
if err := mt . catalog . CreateCollection ( mt . ctx , coll , ts ) ; err != nil {
return err
2022-06-10 13:10:08 +08:00
}
2022-07-22 10:20:29 +08:00
mt . collID2Meta [ coll . CollectionID ] = * coll
mt . collName2ID [ coll . Name ] = coll . CollectionID
2022-06-10 13:10:08 +08:00
return nil
2021-01-19 14:44:03 +08:00
}
2021-09-23 15:10:00 +08:00
// DeleteCollection delete collection
2021-10-13 15:54:33 +08:00
func ( mt * MetaTable ) DeleteCollection ( collID typeutil . UniqueID , ts typeutil . Timestamp , ddOpStr string ) error {
2021-01-19 14:44:03 +08:00
mt . ddLock . Lock ( )
defer mt . ddLock . Unlock ( )
2022-07-22 10:20:29 +08:00
col , ok := mt . collID2Meta [ collID ]
2021-01-19 14:44:03 +08:00
if ! ok {
2021-08-18 14:36:10 +08:00
return fmt . Errorf ( "can't find collection. id = %d" , collID )
2021-01-19 14:44:03 +08:00
}
2021-09-18 11:13:51 +08:00
var aliases [ ] string
// delete collection aliases
for alias , cid := range mt . collAlias2ID {
if cid == collID {
aliases = append ( aliases , alias )
}
}
2021-05-17 19:15:01 +08:00
2022-07-22 10:20:29 +08:00
collection := & model . Collection {
CollectionID : collID ,
Aliases : aliases ,
2022-06-10 13:10:08 +08:00
}
2022-07-22 10:20:29 +08:00
if err := mt . catalog . DropCollection ( mt . ctx , collection , ts ) ; err != nil {
return err
2022-06-10 13:10:08 +08:00
}
2022-07-22 10:20:29 +08:00
// update segID2IndexID
for _ , partition := range col . Partitions {
partID := partition . PartitionID
if segIDMap , ok := mt . partID2IndexedSegID [ partID ] ; ok {
for segID := range segIDMap {
delete ( mt . segID2IndexID , segID )
}
}
delete ( mt . partID2IndexedSegID , partID )
2021-10-13 15:54:33 +08:00
}
2022-07-22 10:20:29 +08:00
for _ , t := range col . FieldIDToIndexID {
delete ( mt . indexID2Meta , t . Value )
2022-06-10 13:10:08 +08:00
}
2022-07-22 10:20:29 +08:00
// delete collection aliases
for _ , alias := range aliases {
delete ( mt . collAlias2ID , alias )
2021-10-21 14:04:36 +08:00
}
2021-01-19 14:44:03 +08:00
2022-07-22 10:20:29 +08:00
delete ( mt . collID2Meta , collID )
delete ( mt . collName2ID , col . Name )
2022-06-10 13:10:08 +08:00
return nil
2021-01-19 14:44:03 +08:00
}
2021-09-23 15:10:00 +08:00
// HasCollection return collection existence
func ( mt * MetaTable ) HasCollection ( collID typeutil . UniqueID , ts typeutil . Timestamp ) bool {
2021-01-19 14:44:03 +08:00
mt . ddLock . RLock ( )
defer mt . ddLock . RUnlock ( )
2021-05-18 14:18:02 +08:00
if ts == 0 {
_ , ok := mt . collID2Meta [ collID ]
return ok
}
2022-07-22 10:20:29 +08:00
return mt . catalog . CollectionExists ( mt . ctx , collID , ts )
2021-01-19 14:44:03 +08:00
}
2022-05-09 20:47:52 +08:00
// GetCollectionIDByName returns the collection ID according to its name.
// Returns an error if no matching ID is found.
func ( mt * MetaTable ) GetCollectionIDByName ( cName string ) ( typeutil . UniqueID , error ) {
mt . ddLock . RLock ( )
defer mt . ddLock . RUnlock ( )
var cID UniqueID
var ok bool
if cID , ok = mt . collName2ID [ cName ] ; ! ok {
return 0 , fmt . Errorf ( "collection ID not found for collection name %s" , cName )
}
return cID , nil
}
2022-06-14 16:18:09 +08:00
// GetCollectionNameByID returns the collection name according to its ID.
// Returns an error if no matching name is found.
func ( mt * MetaTable ) GetCollectionNameByID ( collectionID typeutil . UniqueID ) ( string , error ) {
mt . ddLock . RLock ( )
defer mt . ddLock . RUnlock ( )
col , ok := mt . collID2Meta [ collectionID ]
if ! ok {
return "" , fmt . Errorf ( "can't find collection id : %d" , collectionID )
}
2022-07-22 10:20:29 +08:00
return col . Name , nil
2022-06-14 16:18:09 +08:00
}
2021-09-23 15:10:00 +08:00
// GetCollectionByID return collection meta by collection id
2022-07-22 10:20:29 +08:00
func ( mt * MetaTable ) GetCollectionByID ( collectionID typeutil . UniqueID , ts typeutil . Timestamp ) ( * model . Collection , error ) {
2021-01-21 10:01:29 +08:00
mt . ddLock . RLock ( )
defer mt . ddLock . RUnlock ( )
2021-05-18 14:18:02 +08:00
if ts == 0 {
col , ok := mt . collID2Meta [ collectionID ]
if ! ok {
return nil , fmt . Errorf ( "can't find collection id : %d" , collectionID )
}
2022-07-22 10:20:29 +08:00
return col . Clone ( ) , nil
2022-06-10 13:10:08 +08:00
}
2022-07-22 10:20:29 +08:00
return mt . catalog . GetCollectionByID ( mt . ctx , collectionID , ts )
2021-01-21 10:01:29 +08:00
}
2021-09-23 15:10:00 +08:00
// GetCollectionByName return collection meta by collection name
2022-07-22 10:20:29 +08:00
func ( mt * MetaTable ) GetCollectionByName ( collectionName string , ts typeutil . Timestamp ) ( * model . Collection , error ) {
2021-01-19 14:44:03 +08:00
mt . ddLock . RLock ( )
defer mt . ddLock . RUnlock ( )
2021-05-18 14:18:02 +08:00
if ts == 0 {
vid , ok := mt . collName2ID [ collectionName ]
if ! ok {
2021-09-18 11:13:51 +08:00
if vid , ok = mt . collAlias2ID [ collectionName ] ; ! ok {
return nil , fmt . Errorf ( "can't find collection: " + collectionName )
}
2021-05-18 14:18:02 +08:00
}
col , ok := mt . collID2Meta [ vid ]
if ! ok {
2021-09-13 11:56:42 +08:00
return nil , fmt . Errorf ( "can't find collection %s with id %d" , collectionName , vid )
2021-05-18 14:18:02 +08:00
}
2022-07-22 10:20:29 +08:00
return col . Clone ( ) , nil
2022-06-10 13:10:08 +08:00
}
2022-07-22 10:20:29 +08:00
return mt . catalog . GetCollectionByName ( mt . ctx , collectionName , ts )
2021-02-02 10:09:10 +08:00
}
2021-09-23 15:10:00 +08:00
// ListCollections list all collection names
2022-07-22 10:20:29 +08:00
func ( mt * MetaTable ) ListCollections ( ts typeutil . Timestamp ) ( map [ string ] * model . Collection , error ) {
2021-01-19 14:44:03 +08:00
mt . ddLock . RLock ( )
defer mt . ddLock . RUnlock ( )
2022-07-22 10:20:29 +08:00
cols := make ( map [ string ] * model . Collection )
2021-01-19 14:44:03 +08:00
2021-05-18 14:18:02 +08:00
if ts == 0 {
2021-07-21 18:00:14 +08:00
for collName , collID := range mt . collName2ID {
2022-07-22 10:20:29 +08:00
col := mt . collID2Meta [ collID ]
cols [ collName ] = col . Clone ( )
2021-05-18 14:18:02 +08:00
}
2022-07-22 10:20:29 +08:00
return cols , nil
2021-01-19 14:44:03 +08:00
}
2022-07-22 10:20:29 +08:00
return mt . catalog . ListCollections ( mt . ctx , ts )
2021-01-19 14:44:03 +08:00
}
2021-09-23 15:10:00 +08:00
// ListAliases list all collection aliases
func ( mt * MetaTable ) ListAliases ( collID typeutil . UniqueID ) [ ] string {
2021-09-22 16:20:48 +08:00
mt . ddLock . RLock ( )
defer mt . ddLock . RUnlock ( )
var aliases [ ] string
for alias , cid := range mt . collAlias2ID {
if cid == collID {
aliases = append ( aliases , alias )
}
}
return aliases
}
2021-09-23 15:10:00 +08:00
// ListCollectionVirtualChannels list virtual channels of all collections
2021-11-02 15:50:30 +08:00
func ( mt * MetaTable ) ListCollectionVirtualChannels ( ) map [ typeutil . UniqueID ] [ ] string {
2021-06-04 15:00:34 +08:00
mt . ddLock . RLock ( )
defer mt . ddLock . RUnlock ( )
2021-11-02 15:50:30 +08:00
chanMap := make ( map [ typeutil . UniqueID ] [ ] string )
2021-06-04 15:00:34 +08:00
2021-11-02 15:50:30 +08:00
for id , collInfo := range mt . collID2Meta {
chanMap [ id ] = collInfo . VirtualChannelNames
2021-06-04 15:00:34 +08:00
}
2021-11-02 15:50:30 +08:00
return chanMap
2021-06-04 15:00:34 +08:00
}
2021-09-23 15:10:00 +08:00
// ListCollectionPhysicalChannels list physical channels of all collections
2021-11-02 15:50:30 +08:00
func ( mt * MetaTable ) ListCollectionPhysicalChannels ( ) map [ typeutil . UniqueID ] [ ] string {
2021-06-04 15:00:34 +08:00
mt . ddLock . RLock ( )
defer mt . ddLock . RUnlock ( )
2021-11-02 15:50:30 +08:00
chanMap := make ( map [ typeutil . UniqueID ] [ ] string )
2021-06-04 15:00:34 +08:00
2021-11-02 15:50:30 +08:00
for id , collInfo := range mt . collID2Meta {
chanMap [ id ] = collInfo . PhysicalChannelNames
2021-06-04 15:00:34 +08:00
}
2021-11-02 15:50:30 +08:00
return chanMap
2021-06-04 15:00:34 +08:00
}
2021-09-23 15:10:00 +08:00
// AddPartition add partition
2021-10-13 15:54:33 +08:00
func ( mt * MetaTable ) AddPartition ( collID typeutil . UniqueID , partitionName string , partitionID typeutil . UniqueID , ts typeutil . Timestamp , ddOpStr string ) error {
2021-01-19 14:44:03 +08:00
mt . ddLock . Lock ( )
defer mt . ddLock . Unlock ( )
coll , ok := mt . collID2Meta [ collID ]
if ! ok {
2021-08-18 14:36:10 +08:00
return fmt . Errorf ( "can't find collection. id = %d" , collID )
2021-01-19 14:44:03 +08:00
}
// number of partition tags (except _default) should be limited to 4096 by default
2022-07-22 10:20:29 +08:00
if int64 ( len ( coll . Partitions ) ) >= Params . RootCoordCfg . MaxPartitionNum {
2021-12-23 18:39:11 +08:00
return fmt . Errorf ( "maximum partition's number should be limit to %d" , Params . RootCoordCfg . MaxPartitionNum )
2021-01-19 14:44:03 +08:00
}
2021-07-03 14:36:18 +08:00
2022-07-22 10:20:29 +08:00
for _ , p := range coll . Partitions {
if p . PartitionID == partitionID {
2021-08-18 14:36:10 +08:00
return fmt . Errorf ( "partition id = %d already exists" , partitionID )
2021-01-20 09:36:50 +08:00
}
2022-07-22 10:20:29 +08:00
if p . PartitionName == partitionName {
2021-08-18 14:36:10 +08:00
return fmt . Errorf ( "partition name = %s already exists" , partitionName )
2021-01-19 14:44:03 +08:00
}
2021-07-21 18:00:14 +08:00
// no necessary to check created timestamp
2021-01-19 14:44:03 +08:00
}
2021-01-20 09:36:50 +08:00
2022-08-10 10:22:38 +08:00
partition := & model . Partition {
PartitionID : partitionID ,
PartitionName : partitionName ,
PartitionCreatedTimestamp : ts ,
CollectionID : collID ,
}
coll . Partitions = append ( coll . Partitions , partition )
2021-01-19 14:44:03 +08:00
2022-08-10 10:22:38 +08:00
if err := mt . catalog . CreatePartition ( mt . ctx , partition , ts ) ; err != nil {
2022-07-22 10:20:29 +08:00
return err
2022-06-10 13:10:08 +08:00
}
2022-07-22 10:20:29 +08:00
mt . collID2Meta [ collID ] = coll
2022-06-10 13:10:08 +08:00
return nil
2021-01-19 14:44:03 +08:00
}
2021-09-23 15:10:00 +08:00
// GetPartitionNameByID return partition name by partition id
func ( mt * MetaTable ) GetPartitionNameByID ( collID , partitionID typeutil . UniqueID , ts typeutil . Timestamp ) ( string , error ) {
2021-05-18 14:18:02 +08:00
if ts == 0 {
2021-07-03 14:36:18 +08:00
mt . ddLock . RLock ( )
defer mt . ddLock . RUnlock ( )
2022-07-22 10:20:29 +08:00
col , ok := mt . collID2Meta [ collID ]
2021-05-18 14:18:02 +08:00
if ! ok {
2021-07-03 14:36:18 +08:00
return "" , fmt . Errorf ( "can't find collection id = %d" , collID )
2021-05-18 14:18:02 +08:00
}
2022-07-22 10:20:29 +08:00
for _ , partition := range col . Partitions {
if partition . PartitionID == partitionID {
return partition . PartitionName , nil
2021-05-18 14:18:02 +08:00
}
}
2021-07-03 14:36:18 +08:00
return "" , fmt . Errorf ( "partition %d does not exist" , partitionID )
2021-05-18 14:18:02 +08:00
}
2022-07-22 10:20:29 +08:00
col , err := mt . catalog . GetCollectionByID ( mt . ctx , collID , ts )
2022-06-10 13:10:08 +08:00
if err != nil {
return "" , err
}
2022-07-22 10:20:29 +08:00
for _ , partition := range col . Partitions {
if partition . PartitionID == partitionID {
return partition . PartitionName , nil
2021-05-18 14:18:02 +08:00
}
2021-07-03 14:36:18 +08:00
}
return "" , fmt . Errorf ( "partition %d does not exist" , partitionID )
}
2021-09-23 15:10:00 +08:00
func ( mt * MetaTable ) getPartitionByName ( collID typeutil . UniqueID , partitionName string , ts typeutil . Timestamp ) ( typeutil . UniqueID , error ) {
2021-07-03 14:36:18 +08:00
if ts == 0 {
2022-07-22 10:20:29 +08:00
col , ok := mt . collID2Meta [ collID ]
2021-07-03 14:36:18 +08:00
if ! ok {
return 0 , fmt . Errorf ( "can't find collection id = %d" , collID )
2021-05-18 14:18:02 +08:00
}
2022-07-22 10:20:29 +08:00
for _ , partition := range col . Partitions {
if partition . PartitionName == partitionName {
return partition . PartitionID , nil
2021-07-03 14:36:18 +08:00
}
}
return 0 , fmt . Errorf ( "partition %s does not exist" , partitionName )
}
2022-07-22 10:20:29 +08:00
col , err := mt . catalog . GetCollectionByID ( mt . ctx , collID , ts )
2022-06-10 13:10:08 +08:00
if err != nil {
return 0 , err
}
2022-07-22 10:20:29 +08:00
for _ , partition := range col . Partitions {
if partition . PartitionName == partitionName {
return partition . PartitionID , nil
2021-01-19 14:44:03 +08:00
}
}
2021-07-03 14:36:18 +08:00
return 0 , fmt . Errorf ( "partition %s does not exist" , partitionName )
2021-05-14 21:26:06 +08:00
}
2021-09-23 15:10:00 +08:00
// GetPartitionByName return partition id by partition name
func ( mt * MetaTable ) GetPartitionByName ( collID typeutil . UniqueID , partitionName string , ts typeutil . Timestamp ) ( typeutil . UniqueID , error ) {
2021-05-14 21:26:06 +08:00
mt . ddLock . RLock ( )
defer mt . ddLock . RUnlock ( )
2021-05-18 14:18:02 +08:00
return mt . getPartitionByName ( collID , partitionName , ts )
2021-01-19 14:44:03 +08:00
}
2021-09-23 15:10:00 +08:00
// HasPartition check partition existence
func ( mt * MetaTable ) HasPartition ( collID typeutil . UniqueID , partitionName string , ts typeutil . Timestamp ) bool {
2021-05-14 21:26:06 +08:00
mt . ddLock . RLock ( )
defer mt . ddLock . RUnlock ( )
2021-05-18 14:18:02 +08:00
_ , err := mt . getPartitionByName ( collID , partitionName , ts )
2021-05-14 21:26:06 +08:00
return err == nil
}
2021-09-23 15:10:00 +08:00
// DeletePartition delete partition
2021-10-13 15:54:33 +08:00
func ( mt * MetaTable ) DeletePartition ( collID typeutil . UniqueID , partitionName string , ts typeutil . Timestamp , ddOpStr string ) ( typeutil . UniqueID , error ) {
2021-01-19 14:44:03 +08:00
mt . ddLock . Lock ( )
defer mt . ddLock . Unlock ( )
2022-01-10 19:03:35 +08:00
if partitionName == Params . CommonCfg . DefaultPartitionName {
2021-08-18 14:36:10 +08:00
return 0 , fmt . Errorf ( "default partition cannot be deleted" )
2021-01-19 14:44:03 +08:00
}
2022-07-22 10:20:29 +08:00
col , ok := mt . collID2Meta [ collID ]
2021-01-19 14:44:03 +08:00
if ! ok {
2021-08-18 14:36:10 +08:00
return 0 , fmt . Errorf ( "can't find collection id = %d" , collID )
2021-01-19 14:44:03 +08:00
}
// check tag exists
exist := false
2022-07-22 10:20:29 +08:00
parts := make ( [ ] * model . Partition , 0 , len ( col . Partitions ) )
2021-07-03 14:36:18 +08:00
var partID typeutil . UniqueID
2022-07-22 10:20:29 +08:00
for _ , partition := range col . Partitions {
if partition . PartitionName == partitionName {
partID = partition . PartitionID
2021-07-03 14:36:18 +08:00
exist = true
} else {
2022-07-22 10:20:29 +08:00
parts = append ( parts , partition )
2021-01-19 14:44:03 +08:00
}
}
if ! exist {
2021-08-18 14:36:10 +08:00
return 0 , fmt . Errorf ( "partition %s does not exist" , partitionName )
2021-01-19 14:44:03 +08:00
}
2022-07-22 10:20:29 +08:00
col . Partitions = parts
2022-08-10 10:22:38 +08:00
if err := mt . catalog . DropPartition ( mt . ctx , col . CollectionID , partID , ts ) ; err != nil {
2022-07-22 10:20:29 +08:00
return 0 , err
}
// update cache
mt . collID2Meta [ collID ] = col
if segIDMap , ok := mt . partID2IndexedSegID [ partID ] ; ok {
2021-07-03 20:00:40 +08:00
for segID := range segIDMap {
2022-07-22 10:20:29 +08:00
indexID , ok := mt . segID2IndexID [ segID ]
if ! ok {
continue
}
delete ( mt . segID2IndexID , segID )
indexMeta , ok := mt . indexID2Meta [ indexID ]
if ok {
delete ( indexMeta . SegmentIndexes , segID )
}
2021-01-19 14:44:03 +08:00
}
}
2022-07-22 10:20:29 +08:00
delete ( mt . partID2IndexedSegID , partID )
2021-07-03 20:00:40 +08:00
2022-07-22 10:20:29 +08:00
return partID , nil
}
2022-06-10 13:10:08 +08:00
2022-07-22 10:20:29 +08:00
func ( mt * MetaTable ) updateSegmentIndexMetaCache ( oldIndex * model . Index , index * model . Index ) error {
for _ , segIdxInfo := range index . SegmentIndexes {
if _ , ok := mt . partID2IndexedSegID [ segIdxInfo . PartitionID ] ; ! ok {
segIDMap := map [ typeutil . UniqueID ] bool { segIdxInfo . SegmentID : true }
mt . partID2IndexedSegID [ segIdxInfo . PartitionID ] = segIDMap
} else {
mt . partID2IndexedSegID [ segIdxInfo . PartitionID ] [ segIdxInfo . SegmentID ] = true
}
2021-01-19 14:44:03 +08:00
2022-07-22 10:20:29 +08:00
mt . segID2IndexID [ segIdxInfo . SegmentID ] = index . IndexID
2022-06-10 13:10:08 +08:00
}
2022-07-22 10:20:29 +08:00
for segID , segmentIdx := range index . SegmentIndexes {
oldIndex . SegmentIndexes [ segID ] = segmentIdx
2021-10-21 14:04:36 +08:00
}
2022-07-22 10:20:29 +08:00
return nil
2021-01-19 14:44:03 +08:00
}
2022-07-22 10:20:29 +08:00
// AlterIndex alter index
func ( mt * MetaTable ) AlterIndex ( newIndex * model . Index ) error {
2022-06-10 13:10:08 +08:00
mt . ddLock . Lock ( )
defer mt . ddLock . Unlock ( )
2021-05-24 14:19:52 +08:00
2022-07-22 10:20:29 +08:00
_ , ok := mt . collID2Meta [ newIndex . CollectionID ]
2022-06-07 12:00:07 +08:00
if ! ok {
2022-07-22 10:20:29 +08:00
return fmt . Errorf ( "collection id = %d not found" , newIndex . CollectionID )
2021-09-29 20:26:00 +08:00
}
2021-02-11 08:41:59 +08:00
2022-07-22 10:20:29 +08:00
oldIndex , ok := mt . indexID2Meta [ newIndex . IndexID ]
if ! ok || newIndex . IsDeleted {
log . Error ( "index id not found or has been deleted" , zap . Int64 ( "indexID" , newIndex . IndexID ) )
return fmt . Errorf ( "index id = %d not found" , newIndex . IndexID )
2021-01-21 10:01:29 +08:00
}
2021-03-10 14:45:35 +08:00
2022-07-22 10:20:29 +08:00
if err := mt . catalog . AlterIndex ( mt . ctx , oldIndex , newIndex , metastore . ADD ) ; err != nil {
return err
2022-06-10 13:10:08 +08:00
}
2022-07-22 10:20:29 +08:00
err := mt . updateSegmentIndexMetaCache ( oldIndex , newIndex )
return err
2021-01-21 10:01:29 +08:00
}
2022-06-17 18:08:12 +08:00
func ( mt * MetaTable ) MarkIndexDeleted ( collName , fieldName , indexName string ) error {
mt . ddLock . Lock ( )
defer mt . ddLock . Unlock ( )
2022-06-18 12:50:11 +08:00
collMeta , err := mt . getCollectionInfoInternal ( collName )
2022-06-17 18:08:12 +08:00
if err != nil {
log . Error ( "get collection meta failed" , zap . String ( "collName" , collName ) , zap . Error ( err ) )
return fmt . Errorf ( "collection name = %s not has meta" , collName )
}
2022-06-18 12:50:11 +08:00
fieldSch , err := mt . getFieldSchemaInternal ( collName , fieldName )
2022-06-17 18:08:12 +08:00
if err != nil {
return err
}
2022-07-22 10:20:29 +08:00
var deletedIdxMeta * model . Index
for _ , t := range collMeta . FieldIDToIndexID {
fieldID := t . Key
indexID := t . Value
if fieldID != fieldSch . FieldID {
2022-06-17 18:08:12 +08:00
continue
}
2022-07-22 10:20:29 +08:00
idxMeta , ok := mt . indexID2Meta [ indexID ]
2022-06-17 18:08:12 +08:00
if ! ok {
2022-07-22 10:20:29 +08:00
errMsg := fmt . Errorf ( "index not has meta with ID = %d" , indexID )
log . Error ( "index id not has meta" , zap . Int64 ( "index id" , indexID ) )
2022-06-17 18:08:12 +08:00
return errMsg
}
2022-07-22 10:20:29 +08:00
if idxMeta . IsDeleted {
2022-06-20 15:22:13 +08:00
continue
}
2022-06-17 18:08:12 +08:00
if idxMeta . IndexName != indexName {
continue
}
2022-07-22 10:20:29 +08:00
deletedIdxMeta = idxMeta
2022-06-17 18:08:12 +08:00
}
2022-07-22 10:20:29 +08:00
if deletedIdxMeta == nil {
log . Warn ( "index not found" ,
zap . String ( "collName" , collName ) ,
zap . String ( "fieldName" , fieldName ) ,
2022-06-17 18:08:12 +08:00
zap . String ( "indexName" , indexName ) )
return nil
}
2022-07-22 10:20:29 +08:00
log . Info ( "mark index deleted" ,
zap . String ( "collName" , collName ) ,
zap . String ( "fieldName" , fieldName ) ,
zap . String ( "indexName" , indexName ) ,
zap . Int64 ( "indexID" , deletedIdxMeta . IndexID ) )
2022-06-17 18:08:12 +08:00
2022-07-22 10:20:29 +08:00
// update metastore
newIndex := & model . Index { IsDeleted : true }
if err = mt . catalog . AlterIndex ( mt . ctx , deletedIdxMeta , newIndex , metastore . ADD ) ; err != nil {
2022-06-17 18:08:12 +08:00
return err
}
2022-07-22 10:20:29 +08:00
// update cache
deletedIdxMeta . IsDeleted = true
2022-06-17 18:08:12 +08:00
return nil
}
2021-09-23 15:10:00 +08:00
// DropIndex drop index
2022-06-17 18:08:12 +08:00
// Deprecated, only ut are used.
2021-10-21 14:04:36 +08:00
func ( mt * MetaTable ) DropIndex ( collName , fieldName , indexName string ) ( typeutil . UniqueID , bool , error ) {
2021-02-20 15:38:44 +08:00
mt . ddLock . Lock ( )
defer mt . ddLock . Unlock ( )
collID , ok := mt . collName2ID [ collName ]
if ! ok {
2021-09-28 21:52:20 +08:00
collID , ok = mt . collAlias2ID [ collName ]
if ! ok {
return 0 , false , fmt . Errorf ( "collection name = %s not exist" , collName )
}
2021-02-20 15:38:44 +08:00
}
2022-07-22 10:20:29 +08:00
col , ok := mt . collID2Meta [ collID ]
2021-02-20 15:38:44 +08:00
if ! ok {
2021-08-18 14:36:10 +08:00
return 0 , false , fmt . Errorf ( "collection name = %s not has meta" , collName )
2021-02-20 15:38:44 +08:00
}
2022-06-18 12:50:11 +08:00
fieldSch , err := mt . getFieldSchemaInternal ( collName , fieldName )
2021-02-20 15:38:44 +08:00
if err != nil {
2021-08-18 14:36:10 +08:00
return 0 , false , err
2021-02-20 15:38:44 +08:00
}
2022-07-22 10:20:29 +08:00
fieldIDToIndexID := make ( [ ] common . Int64Tuple , 0 , len ( col . FieldIDToIndexID ) )
2021-02-20 15:38:44 +08:00
var dropIdxID typeutil . UniqueID
2022-07-22 10:20:29 +08:00
for i , t := range col . FieldIDToIndexID {
fieldID := t . Key
indexID := t . Value
if fieldID != fieldSch . FieldID {
fieldIDToIndexID = append ( fieldIDToIndexID , t )
2021-02-20 15:38:44 +08:00
continue
}
2022-07-22 10:20:29 +08:00
idxMeta , ok := mt . indexID2Meta [ indexID ]
if ! ok || idxMeta . IsDeleted || idxMeta . IndexName != indexName {
fieldIDToIndexID = append ( fieldIDToIndexID , t )
log . Warn ( "index id not has meta" , zap . Int64 ( "index id" , indexID ) )
2021-02-20 15:38:44 +08:00
continue
}
2022-07-22 10:20:29 +08:00
dropIdxID = indexID
fieldIDToIndexID = append ( fieldIDToIndexID , col . FieldIDToIndexID [ i + 1 : ] ... )
2021-02-20 15:38:44 +08:00
break
}
2022-07-22 10:20:29 +08:00
if len ( fieldIDToIndexID ) == len ( col . FieldIDToIndexID ) {
2021-02-24 16:25:40 +08:00
log . Warn ( "drop index,index not found" , zap . String ( "collection name" , collName ) , zap . String ( "filed name" , fieldName ) , zap . String ( "index name" , indexName ) )
2021-08-18 14:36:10 +08:00
return 0 , false , nil
2021-02-20 15:38:44 +08:00
}
2022-07-22 10:20:29 +08:00
col . FieldIDToIndexID = fieldIDToIndexID
// update metastore
2022-08-11 12:12:38 +08:00
err = mt . catalog . DropIndex ( mt . ctx , & col , dropIdxID )
2022-06-10 13:10:08 +08:00
if err != nil {
2022-07-22 10:20:29 +08:00
return 0 , false , err
2022-06-10 13:10:08 +08:00
}
2021-02-20 15:38:44 +08:00
2022-07-22 10:20:29 +08:00
// update cache
mt . collID2Meta [ collID ] = col
2022-06-07 12:00:07 +08:00
delete ( mt . indexID2Meta , dropIdxID )
2022-07-22 10:20:29 +08:00
for _ , part := range col . Partitions {
if segIDMap , ok := mt . partID2IndexedSegID [ part . PartitionID ] ; ok {
2021-07-03 20:00:40 +08:00
for segID := range segIDMap {
2022-07-22 10:20:29 +08:00
delete ( mt . segID2IndexID , segID )
2021-02-20 15:38:44 +08:00
}
}
}
2021-07-03 20:00:40 +08:00
2021-08-18 14:36:10 +08:00
return dropIdxID , true , nil
2021-02-20 15:38:44 +08:00
}
2022-06-16 20:12:11 +08:00
func ( mt * MetaTable ) GetInitBuildIDs ( collName , indexName string ) ( [ ] UniqueID , error ) {
mt . ddLock . RLock ( )
defer mt . ddLock . RUnlock ( )
2022-06-18 12:50:11 +08:00
collMeta , err := mt . getCollectionInfoInternal ( collName )
2022-06-16 20:12:11 +08:00
if err != nil {
return nil , err
}
2022-07-22 10:20:29 +08:00
var targetIdxMeta * model . Index
2022-06-21 18:44:12 +08:00
var indexIDCreateTS uint64
2022-07-22 10:20:29 +08:00
for _ , t := range collMeta . FieldIDToIndexID {
idxMeta , ok := mt . indexID2Meta [ t . Value ]
2022-06-16 20:12:11 +08:00
if ok && idxMeta . IndexName == indexName {
2022-07-22 10:20:29 +08:00
targetIdxMeta = idxMeta
2022-06-21 18:44:12 +08:00
indexIDCreateTS = idxMeta . CreateTime
2022-06-16 20:12:11 +08:00
break
}
}
2022-07-22 10:20:29 +08:00
if targetIdxMeta == nil {
2022-06-16 20:12:11 +08:00
log . Warn ( "get init buildIDs, index not found" , zap . String ( "collection name" , collName ) ,
zap . String ( "index name" , indexName ) )
return nil , fmt . Errorf ( "index not found with name = %s in collection %s" , indexName , collName )
}
initBuildIDs := make ( [ ] UniqueID , 0 )
2022-07-22 10:20:29 +08:00
for _ , segIndexInfo := range targetIdxMeta . SegmentIndexes {
if segIndexInfo . EnableIndex && segIndexInfo . CreateTime <= indexIDCreateTS {
2022-06-16 20:12:11 +08:00
initBuildIDs = append ( initBuildIDs , segIndexInfo . BuildID )
}
}
2022-07-22 10:20:29 +08:00
2022-06-16 20:12:11 +08:00
return initBuildIDs , nil
}
2022-06-17 18:08:12 +08:00
func ( mt * MetaTable ) GetBuildIDsBySegIDs ( segIDs [ ] UniqueID ) [ ] UniqueID {
mt . ddLock . RLock ( )
defer mt . ddLock . RUnlock ( )
buildIDs := make ( [ ] UniqueID , 0 )
for _ , segID := range segIDs {
2022-07-22 10:20:29 +08:00
segmentIdx , err := mt . getSegIdxMetaBySegID ( segID )
// skip if not found corresponding index meta
if err != nil {
continue
2022-06-17 18:08:12 +08:00
}
2022-07-22 10:20:29 +08:00
buildIDs = append ( buildIDs , segmentIdx . BuildID )
2022-06-17 18:08:12 +08:00
}
return buildIDs
}
func ( mt * MetaTable ) AlignSegmentsMeta ( collID , partID UniqueID , segIDs map [ UniqueID ] struct { } ) ( [ ] UniqueID , [ ] UniqueID ) {
mt . ddLock . Lock ( )
defer mt . ddLock . Unlock ( )
allIndexID := make ( [ ] UniqueID , 0 )
if collMeta , ok := mt . collID2Meta [ collID ] ; ok {
2022-07-22 10:20:29 +08:00
for _ , tuple := range collMeta . FieldIDToIndexID {
allIndexID = append ( allIndexID , tuple . Value )
2022-06-17 18:08:12 +08:00
}
}
recycledSegIDs := make ( [ ] UniqueID , 0 )
recycledBuildIDs := make ( [ ] UniqueID , 0 )
2022-07-22 10:20:29 +08:00
if segMap , ok := mt . partID2IndexedSegID [ partID ] ; ok {
2022-06-17 18:08:12 +08:00
for segID := range segMap {
if _ , ok := segIDs [ segID ] ; ! ok {
recycledSegIDs = append ( recycledSegIDs , segID )
2022-07-22 10:20:29 +08:00
segmentIdx , err := mt . getSegIdxMetaBySegID ( segID )
// skip if not found corresponding index meta
if err != nil {
continue
2022-06-17 18:08:12 +08:00
}
2022-07-22 10:20:29 +08:00
recycledBuildIDs = append ( recycledBuildIDs , segmentIdx . BuildID )
2022-06-17 18:08:12 +08:00
}
}
}
return recycledSegIDs , recycledBuildIDs
}
func ( mt * MetaTable ) RemoveSegments ( collID , partID UniqueID , segIDs [ ] UniqueID ) error {
mt . ddLock . Lock ( )
defer mt . ddLock . Unlock ( )
log . Info ( "RootCoord MetaTable remove segments" , zap . Int64 ( "collID" , collID ) , zap . Int64 ( "partID" , partID ) ,
zap . Int64s ( "segIDs" , segIDs ) )
allIndexID := make ( [ ] UniqueID , 0 )
if collMeta , ok := mt . collID2Meta [ collID ] ; ok {
2022-07-22 10:20:29 +08:00
for _ , tuple := range collMeta . FieldIDToIndexID {
allIndexID = append ( allIndexID , tuple . Value )
2022-06-17 18:08:12 +08:00
}
}
2022-07-22 10:20:29 +08:00
for _ , indexID := range allIndexID {
deletedSegIdx := make ( map [ int64 ] model . SegmentIndex , len ( segIDs ) )
for _ , segID := range segIDs {
deletedSegIdx [ segID ] = model . SegmentIndex {
Segment : model . Segment {
SegmentID : segID ,
PartitionID : partID ,
} ,
}
2022-06-17 18:08:12 +08:00
}
2022-07-22 10:20:29 +08:00
deletedIdxMeta := & model . Index {
CollectionID : collID ,
IndexID : indexID ,
SegmentIndexes : deletedSegIdx ,
}
if err := mt . catalog . AlterIndex ( mt . ctx , nil , deletedIdxMeta , metastore . DELETE ) ; err != nil {
2022-06-17 18:08:12 +08:00
return err
}
}
2022-07-22 10:20:29 +08:00
// update cache
for _ , segID := range segIDs {
idxID , ok := mt . segID2IndexID [ segID ]
if ! ok {
continue
}
idxMeta , ok := mt . indexID2Meta [ idxID ]
if ! ok {
return fmt . Errorf ( "index meta not found in collectionID %d with idxID: %d" , collID , idxID )
}
delete ( idxMeta . SegmentIndexes , segID )
delete ( mt . segID2IndexID , segID )
delete ( mt . partID2IndexedSegID [ partID ] , segID )
}
2022-06-17 18:08:12 +08:00
return nil
}
2022-07-22 10:20:29 +08:00
func ( mt * MetaTable ) GetDroppedIndex ( ) map [ UniqueID ] [ ] UniqueID {
2022-06-17 18:08:12 +08:00
mt . ddLock . Lock ( )
defer mt . ddLock . Unlock ( )
2022-07-22 10:20:29 +08:00
droppedIndex := make ( map [ UniqueID ] [ ] UniqueID )
2022-06-17 18:08:12 +08:00
for collID , meta := range mt . collID2Meta {
2022-07-22 10:20:29 +08:00
for _ , tuple := range meta . FieldIDToIndexID {
if indexMeta , ok := mt . indexID2Meta [ tuple . Value ] ; ok && indexMeta . IsDeleted {
droppedIndex [ collID ] = append ( droppedIndex [ collID ] , tuple . Value )
2022-06-17 18:08:12 +08:00
}
}
}
return droppedIndex
}
// RecycleDroppedIndex remove the meta about index which is deleted.
2022-07-22 10:20:29 +08:00
// TODO:: Enable time travel
2022-06-17 18:08:12 +08:00
func ( mt * MetaTable ) RecycleDroppedIndex ( ) error {
mt . ddLock . Lock ( )
defer mt . ddLock . Unlock ( )
2022-07-22 10:20:29 +08:00
for collID , colMeta := range mt . collID2Meta {
filedIDToIdxID := Int64TupleSliceToMap ( colMeta . FieldIDToIndexID )
for idx , tuple := range filedIDToIdxID {
dropIdxID := tuple . Value
if idxInfo , ok := mt . indexID2Meta [ dropIdxID ] ; ! ok || idxInfo . IsDeleted {
delete ( filedIDToIdxID , idx )
colMeta . FieldIDToIndexID = Int64TupleMapToSlice ( filedIDToIdxID )
// update metastore
newColMeta := colMeta
2022-08-11 12:12:38 +08:00
if err := mt . catalog . DropIndex ( mt . ctx , & newColMeta , dropIdxID ) ; err != nil {
2022-07-22 10:20:29 +08:00
return err
}
2022-06-17 18:08:12 +08:00
2022-07-22 10:20:29 +08:00
// update cache
mt . collID2Meta [ collID ] = colMeta
delete ( mt . indexID2Meta , dropIdxID )
for _ , part := range colMeta . Partitions {
if segIDMap , ok := mt . partID2IndexedSegID [ part . PartitionID ] ; ok {
for segID := range segIDMap {
delete ( mt . segID2IndexID , segID )
2022-06-17 18:08:12 +08:00
}
}
}
2022-07-22 10:20:29 +08:00
log . Debug ( "recycle dropped index meta" , zap . Int64 ( "collID" , collID ) , zap . Int64 ( "indexID" , dropIdxID ) )
2022-06-17 18:08:12 +08:00
}
}
}
2022-07-22 10:20:29 +08:00
2022-06-17 18:08:12 +08:00
return nil
}
2021-09-23 15:10:00 +08:00
// GetSegmentIndexInfoByID return segment index info by segment id
2022-07-22 10:20:29 +08:00
func ( mt * MetaTable ) GetSegmentIndexInfoByID ( segID typeutil . UniqueID , fieldID int64 , idxName string ) ( model . Index , error ) {
2021-01-21 10:01:29 +08:00
mt . ddLock . RLock ( )
defer mt . ddLock . RUnlock ( )
2022-07-22 10:20:29 +08:00
idxMeta , err := mt . getIdxMetaBySegID ( segID )
if err != nil {
return model . Index { } , err
}
2021-01-21 10:01:29 +08:00
2022-07-22 10:20:29 +08:00
// return default index
if fieldID == - 1 && idxName == "" && ! idxMeta . IsDeleted && idxMeta . IndexName == Params . CommonCfg . DefaultIndexName {
return idxMeta , nil
2021-01-21 10:01:29 +08:00
}
2022-07-22 10:20:29 +08:00
if idxMeta . IndexName == idxName && ! idxMeta . IsDeleted && idxMeta . FieldID == fieldID {
return idxMeta , nil
}
return model . Index { } , fmt . Errorf ( "can't find index name = %s on segment = %d, with filed id = %d" , idxName , segID , fieldID )
2021-01-21 10:01:29 +08:00
}
2022-07-22 10:20:29 +08:00
func ( mt * MetaTable ) GetSegmentIndexInfos ( segID typeutil . UniqueID ) ( model . Index , error ) {
2022-03-30 21:11:28 +08:00
mt . ddLock . RLock ( )
defer mt . ddLock . RUnlock ( )
2022-07-22 10:20:29 +08:00
return mt . getIdxMetaBySegID ( segID )
2022-03-30 21:11:28 +08:00
}
2021-09-23 15:10:00 +08:00
// GetFieldSchema return field schema
2022-07-22 10:20:29 +08:00
func ( mt * MetaTable ) GetFieldSchema ( collName string , fieldName string ) ( model . Field , error ) {
2021-01-21 10:01:29 +08:00
mt . ddLock . RLock ( )
defer mt . ddLock . RUnlock ( )
2022-06-18 12:50:11 +08:00
return mt . getFieldSchemaInternal ( collName , fieldName )
2021-02-02 10:09:10 +08:00
}
2022-07-22 10:20:29 +08:00
func ( mt * MetaTable ) getFieldSchemaInternal ( collName string , fieldName string ) ( model . Field , error ) {
2021-01-21 10:01:29 +08:00
collID , ok := mt . collName2ID [ collName ]
if ! ok {
2021-09-28 21:52:20 +08:00
collID , ok = mt . collAlias2ID [ collName ]
if ! ok {
2022-07-22 10:20:29 +08:00
return model . Field { } , fmt . Errorf ( "collection %s not found" , collName )
2021-09-28 21:52:20 +08:00
}
2021-01-21 10:01:29 +08:00
}
2022-07-22 10:20:29 +08:00
col , ok := mt . collID2Meta [ collID ]
2021-01-21 10:01:29 +08:00
if ! ok {
2022-07-22 10:20:29 +08:00
return model . Field { } , fmt . Errorf ( "collection %s not found" , collName )
2021-01-21 10:01:29 +08:00
}
2022-07-22 10:20:29 +08:00
for _ , field := range col . Fields {
2021-01-21 10:01:29 +08:00
if field . Name == fieldName {
return * field , nil
}
}
2022-07-22 10:20:29 +08:00
return model . Field { } , fmt . Errorf ( "collection %s doesn't have filed %s" , collName , fieldName )
2021-01-21 10:01:29 +08:00
}
2021-12-22 21:31:15 +08:00
// IsSegmentIndexed check if segment has indexed
2022-07-22 10:20:29 +08:00
func ( mt * MetaTable ) IsSegmentIndexed ( segID typeutil . UniqueID , fieldSchema * model . Field , indexParams [ ] * commonpb . KeyValuePair ) bool {
2021-01-21 10:01:29 +08:00
mt . ddLock . RLock ( )
defer mt . ddLock . RUnlock ( )
2022-06-18 12:50:11 +08:00
return mt . isSegmentIndexedInternal ( segID , fieldSchema , indexParams )
2021-02-02 10:09:10 +08:00
}
2022-07-22 10:20:29 +08:00
func ( mt * MetaTable ) isSegmentIndexedInternal ( segID typeutil . UniqueID , fieldSchema * model . Field , indexParams [ ] * commonpb . KeyValuePair ) bool {
index , err := mt . getIdxMetaBySegID ( segID )
if err != nil {
2021-01-21 10:01:29 +08:00
return false
}
2022-07-22 10:20:29 +08:00
segIndex , ok := index . SegmentIndexes [ segID ]
if ok && ! index . IsDeleted &&
index . FieldID == fieldSchema . FieldID &&
EqualKeyPairArray ( indexParams , index . IndexParams ) &&
segIndex . EnableIndex {
return true
2021-01-21 10:01:29 +08:00
}
2022-07-22 10:20:29 +08:00
return false
2021-01-21 10:01:29 +08:00
}
2022-07-22 10:20:29 +08:00
func ( mt * MetaTable ) getCollectionInfoInternal ( collName string ) ( model . Collection , error ) {
2022-05-10 21:07:53 +08:00
collID , ok := mt . collName2ID [ collName ]
if ! ok {
collID , ok = mt . collAlias2ID [ collName ]
if ! ok {
2022-07-22 10:20:29 +08:00
return model . Collection { } , fmt . Errorf ( "collection not found: %s" , collName )
2022-05-10 21:07:53 +08:00
}
}
collMeta , ok := mt . collID2Meta [ collID ]
if ! ok {
2022-07-22 10:20:29 +08:00
return model . Collection { } , fmt . Errorf ( "collection not found: %s" , collName )
2022-05-10 21:07:53 +08:00
}
return collMeta , nil
}
2022-07-22 10:20:29 +08:00
func ( mt * MetaTable ) checkFieldCanBeIndexed ( collMeta model . Collection , fieldSchema model . Field , idxInfo * model . Index ) error {
for _ , tuple := range collMeta . FieldIDToIndexID {
if tuple . Key == fieldSchema . FieldID {
if info , ok := mt . indexID2Meta [ tuple . Value ] ; ok {
if info . IsDeleted {
2022-06-17 18:08:12 +08:00
continue
}
2022-07-22 10:20:29 +08:00
if idxInfo . IndexName != info . IndexName {
2022-05-10 21:07:53 +08:00
return fmt . Errorf (
"creating multiple indexes on same field is not supported, " +
"collection: %s, field: %s, index name: %s, new index name: %s" ,
2022-07-22 10:20:29 +08:00
collMeta . Name , fieldSchema . Name ,
info . IndexName , idxInfo . IndexName )
2022-05-10 21:07:53 +08:00
}
} else {
// TODO: unexpected: what if index id not exist? Meta incomplete.
log . Warn ( "index meta was incomplete, index id missing in indexID2Meta" ,
2022-07-22 10:20:29 +08:00
zap . String ( "collection" , collMeta . Name ) ,
zap . String ( "field" , fieldSchema . Name ) ,
zap . Int64 ( "collection id" , collMeta . CollectionID ) ,
zap . Int64 ( "field id" , fieldSchema . FieldID ) ,
zap . Int64 ( "index id" , tuple . Value ) )
2022-05-10 21:07:53 +08:00
}
}
}
return nil
}
2022-07-22 10:20:29 +08:00
func ( mt * MetaTable ) checkFieldIndexDuplicate ( collMeta model . Collection , fieldSchema model . Field , idxInfo * model . Index ) ( duplicate bool , idx * model . Index , err error ) {
for _ , t := range collMeta . FieldIDToIndexID {
if info , ok := mt . indexID2Meta [ t . Value ] ; ok && ! info . IsDeleted {
2022-05-10 21:07:53 +08:00
if info . IndexName == idxInfo . IndexName {
// the index name must be different for different indexes
2022-07-22 10:20:29 +08:00
if t . Key != fieldSchema . FieldID || ! EqualKeyPairArray ( info . IndexParams , idxInfo . IndexParams ) {
return false , nil , fmt . Errorf ( "index already exists, collection: %s, field: %s, index: %s" , collMeta . Name , fieldSchema . Name , idxInfo . IndexName )
2022-05-10 21:07:53 +08:00
}
// same index name, index params, and fieldId
2022-07-22 10:20:29 +08:00
return true , info , nil
2022-05-10 21:07:53 +08:00
}
}
}
2022-06-21 18:44:12 +08:00
return false , nil , nil
2022-05-10 21:07:53 +08:00
}
2021-09-23 15:10:00 +08:00
// GetNotIndexedSegments return segment ids which have no index
2022-07-22 10:20:29 +08:00
func ( mt * MetaTable ) GetNotIndexedSegments ( collName string , fieldName string , idxInfo * model . Index , segIDs [ ] typeutil . UniqueID ) ( [ ] typeutil . UniqueID , model . Field , error ) {
2022-06-07 12:00:07 +08:00
mt . ddLock . Lock ( )
defer mt . ddLock . Unlock ( )
2022-07-22 10:20:29 +08:00
fieldSchema , err := mt . getFieldSchemaInternal ( collName , fieldName )
2022-04-29 13:35:49 +08:00
if err != nil {
2022-07-22 10:20:29 +08:00
return nil , fieldSchema , err
2022-06-07 12:00:07 +08:00
}
2022-07-22 10:20:29 +08:00
rstID := make ( [ ] typeutil . UniqueID , 0 , 16 )
for _ , segID := range segIDs {
if ok := mt . isSegmentIndexedInternal ( segID , & fieldSchema , idxInfo . IndexParams ) ; ! ok {
rstID = append ( rstID , segID )
}
}
return rstID , fieldSchema , nil
}
// AddIndex add index
func ( mt * MetaTable ) AddIndex ( colName string , fieldName string , idxInfo * model . Index , segIDs [ ] typeutil . UniqueID ) ( bool , error ) {
mt . ddLock . Lock ( )
defer mt . ddLock . Unlock ( )
fieldSchema , err := mt . getFieldSchemaInternal ( colName , fieldName )
2022-06-07 12:00:07 +08:00
if err != nil {
2022-07-22 10:20:29 +08:00
return false , err
2022-04-29 13:35:49 +08:00
}
2022-07-22 10:20:29 +08:00
collMeta , err := mt . getCollectionInfoInternal ( colName )
if err != nil {
// error here if collection not found.
return false , err
}
//TODO:: check index params for scalar field
2022-04-29 13:35:49 +08:00
// set default index type for scalar index
2022-07-22 10:20:29 +08:00
if ! typeutil . IsVectorType ( fieldSchema . DataType ) {
2022-04-29 13:35:49 +08:00
if fieldSchema . DataType == schemapb . DataType_VarChar {
idxInfo . IndexParams = [ ] * commonpb . KeyValuePair { { Key : "index_type" , Value : DefaultStringIndexType } }
} else {
idxInfo . IndexParams = [ ] * commonpb . KeyValuePair { { Key : "index_type" , Value : DefaultIndexType } }
}
}
2021-03-10 16:21:49 +08:00
if idxInfo . IndexParams == nil {
2022-07-22 10:20:29 +08:00
return false , fmt . Errorf ( "index param is nil" )
2021-03-10 16:21:49 +08:00
}
2021-01-21 10:01:29 +08:00
2022-05-10 21:07:53 +08:00
if err := mt . checkFieldCanBeIndexed ( collMeta , fieldSchema , idxInfo ) ; err != nil {
2022-07-22 10:20:29 +08:00
return false , err
2022-05-10 21:07:53 +08:00
}
2021-03-10 16:21:49 +08:00
2022-07-22 10:20:29 +08:00
isDuplicated , dupIdxInfo , err := mt . checkFieldIndexDuplicate ( collMeta , fieldSchema , idxInfo )
2022-05-10 21:07:53 +08:00
if err != nil {
2022-07-22 10:20:29 +08:00
return isDuplicated , err
2021-03-10 16:21:49 +08:00
}
2022-05-05 21:33:51 +08:00
2022-07-22 10:20:29 +08:00
if isDuplicated {
log . Info ( "index already exists, update timestamp for IndexID" ,
zap . Any ( "indexTs" , idxInfo . CreateTime ) ,
zap . Int64 ( "indexID" , dupIdxInfo . IndexID ) )
newIdxMeta := * dupIdxInfo
newIdxMeta . CreateTime = idxInfo . CreateTime
if err := mt . catalog . AlterIndex ( mt . ctx , dupIdxInfo , & newIdxMeta , metastore . ADD ) ; err != nil {
return isDuplicated , err
2022-06-10 13:10:08 +08:00
}
2022-07-22 10:20:29 +08:00
mt . indexID2Meta [ dupIdxInfo . IndexID ] = & newIdxMeta
} else {
segmentIndexes := make ( map [ int64 ] model . SegmentIndex , len ( segIDs ) )
for _ , segID := range segIDs {
segmentIndex := model . SegmentIndex {
Segment : model . Segment {
SegmentID : segID ,
} ,
EnableIndex : false ,
}
segmentIndexes [ segID ] = segmentIndex
2022-06-10 13:10:08 +08:00
}
2021-02-02 10:09:10 +08:00
2022-07-22 10:20:29 +08:00
idxInfo . SegmentIndexes = segmentIndexes
idxInfo . FieldID = fieldSchema . FieldID
idxInfo . CollectionID = collMeta . CollectionID
2021-02-11 08:41:59 +08:00
2022-07-22 10:20:29 +08:00
tuple := common . Int64Tuple {
Key : fieldSchema . FieldID ,
Value : idxInfo . IndexID ,
2022-06-10 13:10:08 +08:00
}
2022-07-22 10:20:29 +08:00
collMeta . FieldIDToIndexID = append ( collMeta . FieldIDToIndexID , tuple )
if err := mt . catalog . CreateIndex ( mt . ctx , & collMeta , idxInfo ) ; err != nil {
return isDuplicated , err
2022-06-21 18:44:12 +08:00
}
2022-07-22 10:20:29 +08:00
mt . collID2Meta [ collMeta . CollectionID ] = collMeta
mt . indexID2Meta [ idxInfo . IndexID ] = idxInfo
2021-02-02 10:09:10 +08:00
}
2022-07-22 10:20:29 +08:00
return isDuplicated , nil
2021-01-21 10:01:29 +08:00
}
2021-09-23 15:10:00 +08:00
// GetIndexByName return index info by index name
2022-07-22 10:20:29 +08:00
func ( mt * MetaTable ) GetIndexByName ( collName , indexName string ) ( model . Collection , [ ] model . Index , error ) {
2021-01-21 10:01:29 +08:00
mt . ddLock . RLock ( )
2021-02-08 15:19:48 +08:00
defer mt . ddLock . RUnlock ( )
2021-01-21 10:01:29 +08:00
collID , ok := mt . collName2ID [ collName ]
if ! ok {
2021-09-28 21:52:20 +08:00
collID , ok = mt . collAlias2ID [ collName ]
if ! ok {
2022-07-22 10:20:29 +08:00
return model . Collection { } , nil , fmt . Errorf ( "collection %s not found" , collName )
2021-09-28 21:52:20 +08:00
}
2021-01-21 10:01:29 +08:00
}
2022-07-22 10:20:29 +08:00
col , ok := mt . collID2Meta [ collID ]
2021-01-21 10:01:29 +08:00
if ! ok {
2022-07-22 10:20:29 +08:00
return model . Collection { } , nil , fmt . Errorf ( "collection %s not found" , collName )
2021-01-21 10:01:29 +08:00
}
2022-07-22 10:20:29 +08:00
rstIndex := make ( [ ] model . Index , 0 , len ( col . FieldIDToIndexID ) )
for _ , t := range col . FieldIDToIndexID {
indexID := t . Value
idxInfo , ok := mt . indexID2Meta [ indexID ]
2021-04-26 15:53:47 +08:00
if ! ok {
2022-07-22 10:20:29 +08:00
return model . Collection { } , nil , fmt . Errorf ( "index id = %d not found" , indexID )
2021-04-26 15:53:47 +08:00
}
2022-07-22 10:20:29 +08:00
if idxInfo . IsDeleted {
2022-06-17 18:08:12 +08:00
continue
}
2021-04-26 15:53:47 +08:00
if indexName == "" || idxInfo . IndexName == indexName {
2022-07-22 10:20:29 +08:00
rstIndex = append ( rstIndex , * idxInfo )
2021-01-21 10:01:29 +08:00
}
}
2022-07-22 10:20:29 +08:00
return col , rstIndex , nil
2021-01-21 10:01:29 +08:00
}
2021-01-27 14:41:56 +08:00
2021-09-23 15:10:00 +08:00
// GetIndexByID return index info by index id
2022-07-22 10:20:29 +08:00
func ( mt * MetaTable ) GetIndexByID ( indexID typeutil . UniqueID ) ( * model . Index , error ) {
2021-01-27 14:41:56 +08:00
mt . ddLock . RLock ( )
2021-02-08 15:19:48 +08:00
defer mt . ddLock . RUnlock ( )
2021-01-27 14:41:56 +08:00
indexInfo , ok := mt . indexID2Meta [ indexID ]
2022-07-22 10:20:29 +08:00
if ! ok || indexInfo . IsDeleted {
2021-03-05 10:15:27 +08:00
return nil , fmt . Errorf ( "cannot find index, id = %d" , indexID )
2021-01-27 14:41:56 +08:00
}
2022-07-22 10:20:29 +08:00
return indexInfo , nil
2021-01-27 14:41:56 +08:00
}
2021-07-03 17:54:25 +08:00
2022-07-22 10:20:29 +08:00
func ( mt * MetaTable ) dupCollectionMeta ( ) map [ typeutil . UniqueID ] model . Collection {
2022-06-17 18:08:12 +08:00
mt . ddLock . RLock ( )
defer mt . ddLock . RUnlock ( )
2022-07-22 10:20:29 +08:00
return mt . collID2Meta
2022-06-17 18:08:12 +08:00
}
2021-09-23 15:10:00 +08:00
func ( mt * MetaTable ) dupMeta ( ) (
2022-07-22 10:20:29 +08:00
map [ typeutil . UniqueID ] model . Collection ,
map [ typeutil . UniqueID ] typeutil . UniqueID ,
map [ typeutil . UniqueID ] model . Index ,
2021-07-03 17:54:25 +08:00
) {
mt . ddLock . RLock ( )
defer mt . ddLock . RUnlock ( )
2022-07-22 10:20:29 +08:00
collID2Meta := make ( map [ typeutil . UniqueID ] model . Collection , len ( mt . collID2Meta ) )
segID2IndexID := make ( map [ typeutil . UniqueID ] typeutil . UniqueID , len ( mt . segID2IndexID ) )
indexID2Meta := make ( map [ typeutil . UniqueID ] model . Index , len ( mt . indexID2Meta ) )
2021-07-03 17:54:25 +08:00
for k , v := range mt . collID2Meta {
collID2Meta [ k ] = v
}
2022-07-22 10:20:29 +08:00
for k , v := range mt . segID2IndexID {
segID2IndexID [ k ] = v
2021-07-03 17:54:25 +08:00
}
for k , v := range mt . indexID2Meta {
2022-07-22 10:20:29 +08:00
indexID2Meta [ k ] = * v
2021-07-03 17:54:25 +08:00
}
2022-07-22 10:20:29 +08:00
return collID2Meta , segID2IndexID , indexID2Meta
2021-07-03 17:54:25 +08:00
}
2021-09-18 11:13:51 +08:00
2021-09-23 15:10:00 +08:00
// AddAlias add collection alias
2021-10-12 17:40:34 +08:00
func ( mt * MetaTable ) AddAlias ( collectionAlias string , collectionName string , ts typeutil . Timestamp ) error {
2021-09-18 11:13:51 +08:00
mt . ddLock . Lock ( )
defer mt . ddLock . Unlock ( )
if _ , ok := mt . collAlias2ID [ collectionAlias ] ; ok {
return fmt . Errorf ( "duplicate collection alias, alias = %s" , collectionAlias )
}
if _ , ok := mt . collName2ID [ collectionAlias ] ; ok {
return fmt . Errorf ( "collection alias collides with existing collection name. collection = %s, alias = %s" , collectionAlias , collectionAlias )
}
id , ok := mt . collName2ID [ collectionName ]
if ! ok {
return fmt . Errorf ( "aliased collection name does not exist, name = %s" , collectionName )
}
2022-08-10 10:22:38 +08:00
alias := & model . Alias {
2022-07-22 10:20:29 +08:00
CollectionID : id ,
2022-08-10 10:22:38 +08:00
Name : collectionAlias ,
CreatedTime : ts ,
2022-06-10 13:10:08 +08:00
}
2022-08-10 10:22:38 +08:00
if err := mt . catalog . CreateAlias ( mt . ctx , alias , ts ) ; err != nil {
2022-07-22 10:20:29 +08:00
return err
2021-09-18 11:13:51 +08:00
}
2022-07-22 10:20:29 +08:00
mt . collAlias2ID [ collectionAlias ] = id
2022-06-10 13:10:08 +08:00
return nil
2021-09-18 11:13:51 +08:00
}
2021-10-12 17:40:34 +08:00
// DropAlias drop collection alias
func ( mt * MetaTable ) DropAlias ( collectionAlias string , ts typeutil . Timestamp ) error {
2021-09-18 11:13:51 +08:00
mt . ddLock . Lock ( )
defer mt . ddLock . Unlock ( )
2022-08-10 10:22:38 +08:00
// TODO: drop alias should be idempotent.
_ , ok := mt . collAlias2ID [ collectionAlias ]
2022-07-22 10:20:29 +08:00
if ! ok {
2021-09-18 11:13:51 +08:00
return fmt . Errorf ( "alias does not exist, alias = %s" , collectionAlias )
}
2022-08-10 10:22:38 +08:00
if err := mt . catalog . DropAlias ( mt . ctx , collectionAlias , ts ) ; err != nil {
2022-07-22 10:20:29 +08:00
return err
2022-06-10 13:10:08 +08:00
}
2022-07-22 10:20:29 +08:00
delete ( mt . collAlias2ID , collectionAlias )
2022-06-10 13:10:08 +08:00
return nil
2021-09-18 11:13:51 +08:00
}
2021-09-23 15:10:00 +08:00
// AlterAlias alter collection alias
2021-10-12 17:40:34 +08:00
func ( mt * MetaTable ) AlterAlias ( collectionAlias string , collectionName string , ts typeutil . Timestamp ) error {
2021-09-18 11:13:51 +08:00
mt . ddLock . Lock ( )
defer mt . ddLock . Unlock ( )
if _ , ok := mt . collAlias2ID [ collectionAlias ] ; ! ok {
return fmt . Errorf ( "alias does not exist, alias = %s" , collectionAlias )
}
id , ok := mt . collName2ID [ collectionName ]
if ! ok {
return fmt . Errorf ( "aliased collection name does not exist, name = %s" , collectionName )
}
2021-10-12 17:40:34 +08:00
2022-08-10 10:22:38 +08:00
alias := & model . Alias {
2022-07-22 10:20:29 +08:00
CollectionID : id ,
2022-08-10 10:22:38 +08:00
Name : collectionAlias ,
CreatedTime : ts ,
2022-06-10 13:10:08 +08:00
}
2022-08-10 10:22:38 +08:00
if err := mt . catalog . AlterAlias ( mt . ctx , alias , ts ) ; err != nil {
2022-07-22 10:20:29 +08:00
return err
2021-09-18 11:13:51 +08:00
}
2022-07-22 10:20:29 +08:00
mt . collAlias2ID [ collectionAlias ] = id
2022-06-10 13:10:08 +08:00
return nil
2021-09-18 11:13:51 +08:00
}
2021-10-08 17:37:53 +08:00
2021-10-15 20:42:45 +08:00
// IsAlias returns true if specific `collectionAlias` is an alias of collection.
2021-10-08 17:37:53 +08:00
func ( mt * MetaTable ) IsAlias ( collectionAlias string ) bool {
mt . ddLock . RLock ( )
defer mt . ddLock . RUnlock ( )
_ , ok := mt . collAlias2ID [ collectionAlias ]
return ok
}
2022-04-11 19:49:34 +08:00
// AddCredential add credential
func ( mt * MetaTable ) AddCredential ( credInfo * internalpb . CredentialInfo ) error {
if credInfo . Username == "" {
return fmt . Errorf ( "username is empty" )
}
2022-08-24 10:02:52 +08:00
mt . permissionLock . Lock ( )
defer mt . permissionLock . Unlock ( )
usernames , err := mt . catalog . ListCredentials ( mt . ctx )
if err != nil {
return err
}
if len ( usernames ) >= Params . ProxyCfg . MaxUserNum {
return errors . New ( "unable to add user because the number of users has reached the limit" )
}
if origin , _ := mt . catalog . GetCredential ( mt . ctx , credInfo . Username ) ; origin != nil {
return fmt . Errorf ( "user already exists: %s" , credInfo . Username )
}
credential := & model . Credential {
Username : credInfo . Username ,
EncryptedPassword : credInfo . EncryptedPassword ,
}
return mt . catalog . CreateCredential ( mt . ctx , credential )
}
2022-08-24 14:32:56 +08:00
// AlterCredential update credential
func ( mt * MetaTable ) AlterCredential ( credInfo * internalpb . CredentialInfo ) error {
if credInfo . Username == "" {
return fmt . Errorf ( "username is empty" )
}
2022-07-22 10:20:29 +08:00
credential := & model . Credential {
Username : credInfo . Username ,
EncryptedPassword : credInfo . EncryptedPassword ,
2022-06-10 13:10:08 +08:00
}
2022-08-24 14:32:56 +08:00
return mt . catalog . AlterCredential ( mt . ctx , credential )
2022-04-11 19:49:34 +08:00
}
// GetCredential get credential by username
2022-08-24 14:32:56 +08:00
func ( mt * MetaTable ) GetCredential ( username string ) ( * internalpb . CredentialInfo , error ) {
2022-07-22 10:20:29 +08:00
credential , err := mt . catalog . GetCredential ( mt . ctx , username )
return model . MarshalCredentialModel ( credential ) , err
2022-04-11 19:49:34 +08:00
}
// DeleteCredential delete credential
func ( mt * MetaTable ) DeleteCredential ( username string ) error {
2022-08-24 10:02:52 +08:00
mt . permissionLock . Lock ( )
defer mt . permissionLock . Unlock ( )
2022-07-22 10:20:29 +08:00
return mt . catalog . DropCredential ( mt . ctx , username )
}
2022-06-10 13:10:08 +08:00
2022-07-22 10:20:29 +08:00
// ListCredentialUsernames list credential usernames
func ( mt * MetaTable ) ListCredentialUsernames ( ) ( * milvuspb . ListCredUsersResponse , error ) {
2022-08-24 10:02:52 +08:00
mt . permissionLock . RLock ( )
defer mt . permissionLock . RUnlock ( )
2022-07-22 10:20:29 +08:00
usernames , err := mt . catalog . ListCredentials ( mt . ctx )
2022-06-10 13:10:08 +08:00
if err != nil {
2022-07-22 10:20:29 +08:00
return nil , fmt . Errorf ( "list credential usernames err:%w" , err )
2022-06-10 13:10:08 +08:00
}
2022-07-22 10:20:29 +08:00
return & milvuspb . ListCredUsersResponse { Usernames : usernames } , nil
2022-04-11 19:49:34 +08:00
}
2022-07-22 10:20:29 +08:00
func ( mt * MetaTable ) getIdxMetaBySegID ( segID int64 ) ( model . Index , error ) {
indexID , ok := mt . segID2IndexID [ segID ]
if ! ok {
return model . Index { } , fmt . Errorf ( "segment not found in meta, segment: %d" , segID )
}
2022-06-10 13:10:08 +08:00
2022-07-22 10:20:29 +08:00
idxMeta , ok := mt . indexID2Meta [ indexID ]
if ! ok {
return model . Index { } , fmt . Errorf ( "segment id: %d not has any index, request index id: %d" , segID , indexID )
}
return * idxMeta , nil
}
func ( mt * MetaTable ) getSegIdxMetaBySegID ( segID int64 ) ( model . SegmentIndex , error ) {
idxMeta , err := mt . getIdxMetaBySegID ( segID )
2022-04-11 19:49:34 +08:00
if err != nil {
2022-07-22 10:20:29 +08:00
return model . SegmentIndex { } , err
2022-06-10 13:10:08 +08:00
}
2022-07-22 10:20:29 +08:00
segmentIdx , ok := idxMeta . SegmentIndexes [ segID ]
if ! ok {
return model . SegmentIndex { } , fmt . Errorf ( "segment id: %d not has any segment index," +
" request index id: %d" , segID , idxMeta . IndexID )
2022-04-11 19:49:34 +08:00
}
2022-07-22 10:20:29 +08:00
return segmentIdx , nil
2022-04-11 19:49:34 +08:00
}
2022-08-04 11:04:34 +08:00
// CreateRole create role
func ( mt * MetaTable ) CreateRole ( tenant string , entity * milvuspb . RoleEntity ) error {
if funcutil . IsEmptyString ( entity . Name ) {
return fmt . Errorf ( "the role name in the role info is empty" )
}
2022-08-24 10:02:52 +08:00
mt . permissionLock . Lock ( )
defer mt . permissionLock . Unlock ( )
results , err := mt . catalog . ListRole ( mt . ctx , tenant , nil , false )
if err != nil {
logger . Error ( "fail to list roles" , zap . Error ( err ) )
return err
}
if len ( results ) >= Params . ProxyCfg . MaxRoleNum {
return errors . New ( "unable to add role because the number of roles has reached the limit" )
}
2022-08-04 11:04:34 +08:00
return mt . catalog . CreateRole ( mt . ctx , tenant , entity )
}
// DropRole drop role info
func ( mt * MetaTable ) DropRole ( tenant string , roleName string ) error {
2022-08-24 10:02:52 +08:00
mt . permissionLock . Lock ( )
defer mt . permissionLock . Unlock ( )
2022-08-04 11:04:34 +08:00
return mt . catalog . DropRole ( mt . ctx , tenant , roleName )
}
// OperateUserRole operate the relationship between a user and a role, including adding a user to a role and removing a user from a role
func ( mt * MetaTable ) OperateUserRole ( tenant string , userEntity * milvuspb . UserEntity , roleEntity * milvuspb . RoleEntity , operateType milvuspb . OperateUserRoleType ) error {
if funcutil . IsEmptyString ( userEntity . Name ) {
return fmt . Errorf ( "username in the user entity is empty" )
}
if funcutil . IsEmptyString ( roleEntity . Name ) {
return fmt . Errorf ( "role name in the role entity is empty" )
}
2022-08-24 10:02:52 +08:00
mt . permissionLock . Lock ( )
defer mt . permissionLock . Unlock ( )
2022-08-23 10:26:53 +08:00
return mt . catalog . AlterUserRole ( mt . ctx , tenant , userEntity , roleEntity , operateType )
2022-08-04 11:04:34 +08:00
}
// SelectRole select role.
// Enter the role condition by the entity param. And this param is nil, which means selecting all roles.
// Get all users that are added to the role by setting the includeUserInfo param to true.
func ( mt * MetaTable ) SelectRole ( tenant string , entity * milvuspb . RoleEntity , includeUserInfo bool ) ( [ ] * milvuspb . RoleResult , error ) {
2022-08-24 10:02:52 +08:00
mt . permissionLock . RLock ( )
defer mt . permissionLock . RUnlock ( )
2022-08-23 10:26:53 +08:00
return mt . catalog . ListRole ( mt . ctx , tenant , entity , includeUserInfo )
2022-08-04 11:04:34 +08:00
}
// SelectUser select user.
// Enter the user condition by the entity param. And this param is nil, which means selecting all users.
// Get all roles that are added the user to by setting the includeRoleInfo param to true.
func ( mt * MetaTable ) SelectUser ( tenant string , entity * milvuspb . UserEntity , includeRoleInfo bool ) ( [ ] * milvuspb . UserResult , error ) {
2022-08-24 10:02:52 +08:00
mt . permissionLock . RLock ( )
defer mt . permissionLock . RUnlock ( )
2022-08-23 10:26:53 +08:00
return mt . catalog . ListUser ( mt . ctx , tenant , entity , includeRoleInfo )
2022-08-04 11:04:34 +08:00
}
// OperatePrivilege grant or revoke privilege by setting the operateType param
func ( mt * MetaTable ) OperatePrivilege ( tenant string , entity * milvuspb . GrantEntity , operateType milvuspb . OperatePrivilegeType ) error {
if funcutil . IsEmptyString ( entity . ObjectName ) {
return fmt . Errorf ( "the object name in the grant entity is empty" )
}
if entity . Object == nil || funcutil . IsEmptyString ( entity . Object . Name ) {
return fmt . Errorf ( "the object entity in the grant entity is invalid" )
}
if entity . Role == nil || funcutil . IsEmptyString ( entity . Role . Name ) {
return fmt . Errorf ( "the role entity in the grant entity is invalid" )
}
if entity . Grantor == nil {
return fmt . Errorf ( "the grantor in the grant entity is empty" )
}
if entity . Grantor . Privilege == nil || funcutil . IsEmptyString ( entity . Grantor . Privilege . Name ) {
return fmt . Errorf ( "the privilege name in the grant entity is empty" )
}
if entity . Grantor . User == nil || funcutil . IsEmptyString ( entity . Grantor . User . Name ) {
return fmt . Errorf ( "the grantor name in the grant entity is empty" )
}
if ! funcutil . IsRevoke ( operateType ) && ! funcutil . IsGrant ( operateType ) {
return fmt . Errorf ( "the operate type in the grant entity is invalid" )
}
2022-08-24 10:02:52 +08:00
mt . permissionLock . Lock ( )
defer mt . permissionLock . Unlock ( )
2022-08-23 10:26:53 +08:00
return mt . catalog . AlterGrant ( mt . ctx , tenant , entity , operateType )
2022-08-04 11:04:34 +08:00
}
// SelectGrant select grant
// The principal entity MUST be not empty in the grant entity
// The resource entity and the resource name are optional, and the two params should be not empty together when you select some grants about the resource kind.
func ( mt * MetaTable ) SelectGrant ( tenant string , entity * milvuspb . GrantEntity ) ( [ ] * milvuspb . GrantEntity , error ) {
var entities [ ] * milvuspb . GrantEntity
if entity . Role == nil || funcutil . IsEmptyString ( entity . Role . Name ) {
return entities , fmt . Errorf ( "the role entity in the grant entity is invalid" )
}
2022-08-24 10:02:52 +08:00
mt . permissionLock . RLock ( )
defer mt . permissionLock . RUnlock ( )
2022-08-23 10:26:53 +08:00
return mt . catalog . ListGrant ( mt . ctx , tenant , entity )
2022-08-04 11:04:34 +08:00
}
func ( mt * MetaTable ) ListPolicy ( tenant string ) ( [ ] string , error ) {
2022-08-24 10:02:52 +08:00
mt . permissionLock . RLock ( )
defer mt . permissionLock . RUnlock ( )
2022-08-04 11:04:34 +08:00
return mt . catalog . ListPolicy ( mt . ctx , tenant )
}
func ( mt * MetaTable ) ListUserRole ( tenant string ) ( [ ] string , error ) {
2022-08-24 10:02:52 +08:00
mt . permissionLock . RLock ( )
defer mt . permissionLock . RUnlock ( )
2022-08-04 11:04:34 +08:00
return mt . catalog . ListUserRole ( mt . ctx , tenant )
}