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-08-25 15:48:54 +08:00
"go.uber.org/zap"
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"
2022-04-11 19:49:34 +08:00
"github.com/milvus-io/milvus/internal/proto/internalpb"
"github.com/milvus-io/milvus/internal/proto/milvuspb"
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"
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
2022-08-25 15:48:54 +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 )
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
}
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-08-25 15:48:54 +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)
//}
//
//for _, t := range col.FieldIDToIndexID {
// delete(mt.indexID2Meta, t.Value)
//}
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
2022-08-25 15:48:54 +08:00
//if segIDMap, ok := mt.partID2IndexedSegID[partID]; ok {
// for segID := range segIDMap {
// indexID, ok := mt.segID2IndexID[segID]
// if !ok {
// continue
// }
// delete(mt.segID2IndexID, segID)
//
// indexMeta, ok := mt.indexID2Meta[indexID]
// if ok {
// delete(indexMeta.SegmentIndexes, segID)
// }
// }
//}
//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
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-08-25 15:48:54 +08:00
//func (mt *MetaTable) IsSegmentIndexed(segID typeutil.UniqueID, fieldSchema *model.Field, indexParams []*commonpb.KeyValuePair) bool {
// mt.ddLock.RLock()
// defer mt.ddLock.RUnlock()
// return mt.isSegmentIndexedInternal(segID, fieldSchema, indexParams)
//}
//func (mt *MetaTable) isSegmentIndexedInternal(segID typeutil.UniqueID, fieldSchema *model.Field, indexParams []*commonpb.KeyValuePair) bool {
// index, err := mt.getIdxMetaBySegID(segID)
// if err != nil {
// return false
// }
//
// segIndex, ok := index.SegmentIndexes[segID]
// if ok && !index.IsDeleted &&
// index.FieldID == fieldSchema.FieldID &&
// EqualKeyPairArray(indexParams, index.IndexParams) &&
// segIndex.EnableIndex {
// return true
// }
//
// 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-08-25 15:48:54 +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 {
// continue
// }
//
// if idxInfo.IndexName != info.IndexName {
// return fmt.Errorf(
// "creating multiple indexes on same field is not supported, "+
// "collection: %s, field: %s, index name: %s, new index name: %s",
// collMeta.Name, fieldSchema.Name,
// info.IndexName, idxInfo.IndexName)
// }
// } else {
// // TODO: unexpected: what if index id not exist? Meta incomplete.
// log.Warn("index meta was incomplete, index id missing in indexID2Meta",
// 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))
// }
// }
// }
// return nil
//}
//
//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 {
// if info.IndexName == idxInfo.IndexName {
// // the index name must be different for different indexes
// 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)
// }
//
// // same index name, index params, and fieldId
// return true, info, nil
// }
// }
// }
// return false, nil, nil
//}
//
//// GetNotIndexedSegments return segment ids which have no index
//func (mt *MetaTable) GetNotIndexedSegments(collName string, fieldName string, idxInfo *model.Index, segIDs []typeutil.UniqueID) ([]typeutil.UniqueID, model.Field, error) {
// mt.ddLock.Lock()
// defer mt.ddLock.Unlock()
//
// fieldSchema, err := mt.getFieldSchemaInternal(collName, fieldName)
// if err != nil {
// return nil, fieldSchema, err
// }
//
// 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
//}
2022-07-22 10:20:29 +08:00
// AddIndex add index
2022-08-25 15:48:54 +08:00
//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)
// if err != nil {
// return false, err
// }
//
// collMeta, err := mt.getCollectionInfoInternal(colName)
// if err != nil {
// // error here if collection not found.
// return false, err
// }
//
// //TODO:: check index params for scalar field
// // set default index type for scalar index
// if !typeutil.IsVectorType(fieldSchema.DataType) {
// 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}}
// }
// }
//
// if idxInfo.IndexParams == nil {
// return false, fmt.Errorf("index param is nil")
// }
//
// if err := mt.checkFieldCanBeIndexed(collMeta, fieldSchema, idxInfo); err != nil {
// return false, err
// }
//
// isDuplicated, dupIdxInfo, err := mt.checkFieldIndexDuplicate(collMeta, fieldSchema, idxInfo)
// if err != nil {
// return isDuplicated, err
// }
//
// 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
// }
// 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
// }
//
// idxInfo.SegmentIndexes = segmentIndexes
// idxInfo.FieldID = fieldSchema.FieldID
// idxInfo.CollectionID = collMeta.CollectionID
//
// tuple := common.Int64Tuple{
// Key: fieldSchema.FieldID,
// Value: idxInfo.IndexID,
// }
// collMeta.FieldIDToIndexID = append(collMeta.FieldIDToIndexID, tuple)
// if err := mt.catalog.CreateIndex(mt.ctx, &collMeta, idxInfo); err != nil {
// return isDuplicated, err
// }
//
// mt.collID2Meta[collMeta.CollectionID] = collMeta
// mt.indexID2Meta[idxInfo.IndexID] = idxInfo
// }
//
// return isDuplicated, nil
//}
//
//// GetIndexByName return index info by index name
//func (mt *MetaTable) GetIndexByName(collName, indexName string) (model.Collection, []model.Index, error) {
// mt.ddLock.RLock()
// defer mt.ddLock.RUnlock()
//
// collID, ok := mt.collName2ID[collName]
// if !ok {
// collID, ok = mt.collAlias2ID[collName]
// if !ok {
// return model.Collection{}, nil, fmt.Errorf("collection %s not found", collName)
// }
// }
// col, ok := mt.collID2Meta[collID]
// if !ok {
// return model.Collection{}, nil, fmt.Errorf("collection %s not found", collName)
// }
//
// rstIndex := make([]model.Index, 0, len(col.FieldIDToIndexID))
// for _, t := range col.FieldIDToIndexID {
// indexID := t.Value
// idxInfo, ok := mt.indexID2Meta[indexID]
// if !ok {
// return model.Collection{}, nil, fmt.Errorf("index id = %d not found", indexID)
// }
// if idxInfo.IsDeleted {
// continue
// }
// if indexName == "" || idxInfo.IndexName == indexName {
// rstIndex = append(rstIndex, *idxInfo)
// }
// }
// return col, rstIndex, nil
//}
//
//// GetIndexByID return index info by index id
//func (mt *MetaTable) GetIndexByID(indexID typeutil.UniqueID) (*model.Index, error) {
// mt.ddLock.RLock()
// defer mt.ddLock.RUnlock()
//
// indexInfo, ok := mt.indexID2Meta[indexID]
// if !ok || indexInfo.IsDeleted {
// return nil, fmt.Errorf("cannot find index, id = %d", indexID)
// }
// return indexInfo, nil
//}
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
}
2022-08-25 15:48:54 +08:00
//func (mt *MetaTable) dupMeta() (
// map[typeutil.UniqueID]model.Collection,
// map[typeutil.UniqueID]typeutil.UniqueID,
// map[typeutil.UniqueID]model.Index,
//) {
// mt.ddLock.RLock()
// defer mt.ddLock.RUnlock()
//
// 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))
// for k, v := range mt.collID2Meta {
// collID2Meta[k] = v
// }
// //for k, v := range mt.segID2IndexID {
// // segID2IndexID[k] = v
// //}
// //for k, v := range mt.indexID2Meta {
// // indexID2Meta[k] = *v
// //}
// return collID2Meta, nil, nil
//}
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 {
2022-08-26 19:22:56 +08:00
errMsg := "unable to add user because the number of users has reached the limit"
log . Error ( errMsg , zap . Int ( "max_user_num" , Params . ProxyCfg . MaxUserNum ) )
return errors . New ( errMsg )
2022-08-24 10:02:52 +08:00
}
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
2022-08-26 19:22:56 +08:00
mt . permissionLock . Lock ( )
defer mt . permissionLock . Unlock ( )
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-08-26 19:22:56 +08:00
mt . permissionLock . RLock ( )
defer mt . permissionLock . RUnlock ( )
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-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 {
2022-08-26 19:22:56 +08:00
errMsg := "unable to add role because the number of roles has reached the limit"
log . Error ( errMsg , zap . Int ( "max_role_num" , Params . ProxyCfg . MaxRoleNum ) )
return errors . New ( errMsg )
2022-08-24 10:02:52 +08:00
}
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
}
2022-08-26 19:22:56 +08:00
func ( mt * MetaTable ) DropGrant ( tenant string , role * milvuspb . RoleEntity ) error {
if role == nil || funcutil . IsEmptyString ( role . Name ) {
return fmt . Errorf ( "the role entity is invalid when dropping the grant" )
}
mt . permissionLock . Lock ( )
defer mt . permissionLock . Unlock ( )
return mt . catalog . DeleteGrant ( mt . ctx , tenant , role )
}
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 )
}