提交 9203bdf8 编写于 作者: G groot

rename c++sdk

Signed-off-by: Ngroot <yihua.mo@zilliz.com>
上级 fcb56568
......@@ -22,52 +22,53 @@
namespace {
const char* TABLE_NAME = milvus_sdk::Utils::GenTableName().c_str();
const char* COLLECTION_NAME = milvus_sdk::Utils::GenCollectionName().c_str();
constexpr int64_t TABLE_DIMENSION = 512;
constexpr int64_t TABLE_INDEX_FILE_SIZE = 128;
constexpr milvus::MetricType TABLE_METRIC_TYPE = milvus::MetricType::TANIMOTO;
constexpr int64_t BATCH_ROW_COUNT = 100000;
constexpr int64_t COLLECTION_DIMENSION = 512;
constexpr int64_t COLLECTION_INDEX_FILE_SIZE = 128;
constexpr milvus::MetricType COLLECTION_METRIC_TYPE = milvus::MetricType::TANIMOTO;
constexpr int64_t BATCH_ENTITY_COUNT = 100000;
constexpr int64_t NQ = 5;
constexpr int64_t TOP_K = 10;
constexpr int64_t NPROBE = 32;
constexpr int64_t SEARCH_TARGET = 5000; // change this value, result is different, ensure less than BATCH_ROW_COUNT
constexpr int64_t ADD_VECTOR_LOOP = 20;
constexpr int64_t SEARCH_TARGET = 5000; // change this value, result is different, ensure less than BATCH_ENTITY_COUNT
constexpr int64_t ADD_ENTITY_LOOP = 20;
constexpr milvus::IndexType INDEX_TYPE = milvus::IndexType::IVFFLAT;
milvus::TableSchema
BuildTableSchema() {
milvus::TableSchema tb_schema = {TABLE_NAME, TABLE_DIMENSION, TABLE_INDEX_FILE_SIZE, TABLE_METRIC_TYPE};
return tb_schema;
milvus::CollectionParam
BuildCollectionParam() {
milvus::CollectionParam
collection_param = {COLLECTION_NAME, COLLECTION_DIMENSION, COLLECTION_INDEX_FILE_SIZE, COLLECTION_METRIC_TYPE};
return collection_param;
}
milvus::IndexParam
BuildIndexParam() {
JSON json_params = {{"nlist", 1024}};
milvus::IndexParam index_param = {TABLE_NAME, INDEX_TYPE, json_params.dump()};
milvus::IndexParam index_param = {COLLECTION_NAME, INDEX_TYPE, json_params.dump()};
return index_param;
}
void
BuildBinaryVectors(int64_t from, int64_t to, std::vector<milvus::RowRecord>& vector_record_array,
std::vector<int64_t>& record_ids, int64_t dimension) {
BuildBinaryVectors(int64_t from, int64_t to, std::vector<milvus::Entity>& entity_array,
std::vector<int64_t>& entity_ids, int64_t dimension) {
if (to <= from) {
return;
}
vector_record_array.clear();
record_ids.clear();
entity_array.clear();
entity_ids.clear();
int64_t dim_byte = dimension/8;
for (int64_t k = from; k < to; k++) {
milvus::RowRecord record;
record.binary_data.resize(dim_byte);
milvus::Entity entity;
entity.binary_data.resize(dim_byte);
for (int64_t i = 0; i < dim_byte; i++) {
record.binary_data[i] = (uint8_t)lrand48();
entity.binary_data[i] = (uint8_t)lrand48();
}
vector_record_array.emplace_back(record);
record_ids.push_back(k);
entity_array.emplace_back(entity);
entity_ids.push_back(k);
}
}
......@@ -84,54 +85,54 @@ ClientTest::Test(const std::string& address, const std::string& port) {
std::cout << "Connect function call status: " << stat.message() << std::endl;
}
{ // create table
milvus::TableSchema tb_schema = BuildTableSchema();
stat = conn->CreateTable(tb_schema);
std::cout << "CreateTable function call status: " << stat.message() << std::endl;
milvus_sdk::Utils::PrintTableSchema(tb_schema);
{ // create collection
milvus::CollectionParam collection_param = BuildCollectionParam();
stat = conn->CreateCollection(collection_param);
std::cout << "CreateCollection function call status: " << stat.message() << std::endl;
milvus_sdk::Utils::PrintCollectionParam(collection_param);
bool has_table = conn->HasTable(tb_schema.table_name);
if (has_table) {
std::cout << "Table is created" << std::endl;
bool has_collection = conn->HasCollection(collection_param.collection_name);
if (has_collection) {
std::cout << "Collection is created" << std::endl;
}
}
std::vector<std::pair<int64_t, milvus::RowRecord>> search_record_array;
std::vector<std::pair<int64_t, milvus::Entity>> search_entity_array;
{ // insert vectors
for (int i = 0; i < ADD_VECTOR_LOOP; i++) {
std::vector<milvus::RowRecord> record_array;
std::vector<int64_t> record_ids;
int64_t begin_index = i * BATCH_ROW_COUNT;
for (int i = 0; i < ADD_ENTITY_LOOP; i++) {
std::vector<milvus::Entity> entity_array;
std::vector<int64_t> entity_ids;
int64_t begin_index = i * BATCH_ENTITY_COUNT;
{ // generate vectors
milvus_sdk::TimeRecorder rc("Build vectors No." + std::to_string(i));
milvus_sdk::TimeRecorder rc("Build entities No." + std::to_string(i));
BuildBinaryVectors(begin_index,
begin_index + BATCH_ROW_COUNT,
record_array,
record_ids,
TABLE_DIMENSION);
begin_index + BATCH_ENTITY_COUNT,
entity_array,
entity_ids,
COLLECTION_DIMENSION);
}
if (search_record_array.size() < NQ) {
search_record_array.push_back(std::make_pair(record_ids[SEARCH_TARGET], record_array[SEARCH_TARGET]));
if (search_entity_array.size() < NQ) {
search_entity_array.push_back(std::make_pair(entity_ids[SEARCH_TARGET], entity_array[SEARCH_TARGET]));
}
std::string title = "Insert " + std::to_string(record_array.size()) + " vectors No." + std::to_string(i);
std::string title = "Insert " + std::to_string(entity_array.size()) + " entities No." + std::to_string(i);
milvus_sdk::TimeRecorder rc(title);
stat = conn->Insert(TABLE_NAME, "", record_array, record_ids);
std::cout << "InsertVector function call status: " << stat.message() << std::endl;
std::cout << "Returned id array count: " << record_ids.size() << std::endl;
stat = conn->Insert(COLLECTION_NAME, "", entity_array, entity_ids);
std::cout << "Insert function call status: " << stat.message() << std::endl;
std::cout << "Returned id array count: " << entity_ids.size() << std::endl;
}
}
{ // flush buffer
stat = conn->FlushTable(TABLE_NAME);
std::cout << "FlushTable function call status: " << stat.message() << std::endl;
stat = conn->FlushCollection(COLLECTION_NAME);
std::cout << "FlushCollection function call status: " << stat.message() << std::endl;
}
{ // search vectors
std::vector<std::string> partition_tags;
milvus::TopKQueryResult topk_query_result;
milvus_sdk::Utils::DoSearch(conn, TABLE_NAME, partition_tags, TOP_K, NPROBE, search_record_array,
milvus_sdk::Utils::DoSearch(conn, COLLECTION_NAME, partition_tags, TOP_K, NPROBE, search_entity_array,
topk_query_result);
}
......@@ -144,7 +145,7 @@ ClientTest::Test(const std::string& address, const std::string& port) {
std::cout << "CreateIndex function call status: " << stat.message() << std::endl;
milvus::IndexParam index2;
stat = conn->DescribeIndex(TABLE_NAME, index2);
stat = conn->DescribeIndex(COLLECTION_NAME, index2);
std::cout << "DescribeIndex function call status: " << stat.message() << std::endl;
milvus_sdk::Utils::PrintIndexParam(index2);
}
......@@ -152,13 +153,13 @@ ClientTest::Test(const std::string& address, const std::string& port) {
{ // search vectors
std::vector<std::string> partition_tags;
milvus::TopKQueryResult topk_query_result;
milvus_sdk::Utils::DoSearch(conn, TABLE_NAME, partition_tags, TOP_K, NPROBE, search_record_array,
milvus_sdk::Utils::DoSearch(conn, COLLECTION_NAME, partition_tags, TOP_K, NPROBE, search_entity_array,
topk_query_result);
}
{ // drop table
stat = conn->DropTable(TABLE_NAME);
std::cout << "DropTable function call status: " << stat.message() << std::endl;
{ // drop collection
stat = conn->DropCollection(COLLECTION_NAME);
std::cout << "DropCollection function call status: " << stat.message() << std::endl;
}
milvus::Connection::Destroy(conn);
......
......@@ -22,12 +22,12 @@
namespace {
const char* TABLE_NAME = milvus_sdk::Utils::GenTableName().c_str();
const char* COLLECTION_NAME = milvus_sdk::Utils::GenCollectionName().c_str();
constexpr int64_t TABLE_DIMENSION = 512;
constexpr int64_t TABLE_INDEX_FILE_SIZE = 1024;
constexpr milvus::MetricType TABLE_METRIC_TYPE = milvus::MetricType::L2;
constexpr int64_t BATCH_ROW_COUNT = 10000;
constexpr int64_t COLLECTION_DIMENSION = 512;
constexpr int64_t COLLECTION_INDEX_FILE_SIZE = 1024;
constexpr milvus::MetricType COLLECTION_METRIC_TYPE = milvus::MetricType::L2;
constexpr int64_t BATCH_ENTITY_COUNT = 10000;
constexpr int64_t NQ = 5;
constexpr int64_t TOP_K = 10;
constexpr int64_t NPROBE = 32;
......@@ -36,27 +36,45 @@ constexpr milvus::IndexType INDEX_TYPE = milvus::IndexType::IVFSQ8;
constexpr int32_t PARTITION_COUNT = 5;
constexpr int32_t TARGET_PARTITION = 3;
milvus::TableSchema
BuildTableSchema() {
milvus::TableSchema tb_schema = {TABLE_NAME, TABLE_DIMENSION, TABLE_INDEX_FILE_SIZE, TABLE_METRIC_TYPE};
return tb_schema;
milvus::CollectionParam
BuildCollectionParam() {
milvus::CollectionParam
collection_param = {COLLECTION_NAME, COLLECTION_DIMENSION, COLLECTION_INDEX_FILE_SIZE, COLLECTION_METRIC_TYPE};
return collection_param;
}
milvus::PartitionParam
BuildPartitionParam(int32_t index) {
std::string tag = std::to_string(index);
std::string partition_name = std::string(TABLE_NAME) + "_" + tag;
milvus::PartitionParam partition_param = {TABLE_NAME, tag};
std::string partition_name = std::string(COLLECTION_NAME) + "_" + tag;
milvus::PartitionParam partition_param = {COLLECTION_NAME, tag};
return partition_param;
}
milvus::IndexParam
BuildIndexParam() {
JSON json_params = {{"nlist", 16384}};
milvus::IndexParam index_param = {TABLE_NAME, INDEX_TYPE, json_params.dump()};
milvus::IndexParam index_param = {COLLECTION_NAME, INDEX_TYPE, json_params.dump()};
return index_param;
}
void
CountCollection(std::shared_ptr<milvus::Connection>& conn) {
int64_t entity_count = 0;
auto stat = conn->CountCollection(COLLECTION_NAME, entity_count);
std::cout << COLLECTION_NAME << "(" << entity_count << " entities)" << std::endl;
}
void
ShowCollectionInfo(std::shared_ptr<milvus::Connection>& conn) {
CountCollection(conn);
milvus::CollectionInfo collection_info;
auto stat = conn->ShowCollectionInfo(COLLECTION_NAME, collection_info);
milvus_sdk::Utils::PrintCollectionInfo(collection_info);
std::cout << "ShowCollectionInfo function call status: " << stat.message() << std::endl;
}
} // namespace
void
......@@ -70,11 +88,11 @@ ClientTest::Test(const std::string& address, const std::string& port) {
std::cout << "Connect function call status: " << stat.message() << std::endl;
}
{ // create table
milvus::TableSchema tb_schema = BuildTableSchema();
stat = conn->CreateTable(tb_schema);
std::cout << "CreateTable function call status: " << stat.message() << std::endl;
milvus_sdk::Utils::PrintTableSchema(tb_schema);
{ // create collection
milvus::CollectionParam tb_schema = BuildCollectionParam();
stat = conn->CreateCollection(tb_schema);
std::cout << "CreateCollection function call status: " << stat.message() << std::endl;
milvus_sdk::Utils::PrintCollectionParam(tb_schema);
}
{ // create partition
......@@ -87,7 +105,7 @@ ClientTest::Test(const std::string& address, const std::string& port) {
// show partitions
milvus::PartitionTagList partition_array;
stat = conn->ShowPartitions(TABLE_NAME, partition_array);
stat = conn->ShowPartitions(COLLECTION_NAME, partition_array);
std::cout << partition_array.size() << " partitions created:" << std::endl;
for (auto& partition_tag : partition_array) {
......@@ -96,64 +114,56 @@ ClientTest::Test(const std::string& address, const std::string& port) {
}
{ // insert vectors
milvus_sdk::TimeRecorder rc("All vectors");
milvus_sdk::TimeRecorder rc("All entities");
for (int i = 0; i < PARTITION_COUNT * 5; i++) {
std::vector<milvus::RowRecord> record_array;
std::vector<int64_t> record_ids;
int64_t begin_index = i * BATCH_ROW_COUNT;
std::vector<milvus::Entity> entity_array;
std::vector<int64_t> entity_ids;
int64_t begin_index = i * BATCH_ENTITY_COUNT;
{ // generate vectors
milvus_sdk::TimeRecorder rc("Build vectors No." + std::to_string(i));
milvus_sdk::Utils::BuildVectors(begin_index, begin_index + BATCH_ROW_COUNT, record_array, record_ids,
TABLE_DIMENSION);
milvus_sdk::TimeRecorder rc("Build entities No." + std::to_string(i));
milvus_sdk::Utils::BuildEntities(begin_index,
begin_index + BATCH_ENTITY_COUNT,
entity_array,
entity_ids,
COLLECTION_DIMENSION);
}
std::string title = "Insert " + std::to_string(record_array.size()) + " vectors No." + std::to_string(i);
std::string title = "Insert " + std::to_string(entity_array.size()) + " entities No." + std::to_string(i);
milvus_sdk::TimeRecorder rc(title);
stat = conn->Insert(TABLE_NAME, std::to_string(i % PARTITION_COUNT), record_array, record_ids);
stat = conn->Insert(COLLECTION_NAME, std::to_string(i % PARTITION_COUNT), entity_array, entity_ids);
}
}
{ // flush buffer
stat = conn->FlushTable(TABLE_NAME);
std::cout << "FlushTable function call status: " << stat.message() << std::endl;
stat = conn->FlushCollection(COLLECTION_NAME);
std::cout << "FlushCollection function call status: " << stat.message() << std::endl;
}
{ // table row count
int64_t row_count = 0;
stat = conn->CountTable(TABLE_NAME, row_count);
std::cout << TABLE_NAME << "(" << row_count << " rows)" << std::endl;
}
ShowCollectionInfo(conn);
{ // get table information
milvus::TableInfo table_info;
stat = conn->ShowTableInfo(TABLE_NAME, table_info);
milvus_sdk::Utils::PrintTableInfo(table_info);
std::cout << "ShowTableInfo function call status: " << stat.message() << std::endl;
}
std::vector<std::pair<int64_t, milvus::RowRecord>> search_record_array;
std::vector<std::pair<int64_t, milvus::Entity>> search_entity_array;
{ // build search vectors
std::vector<milvus::RowRecord> record_array;
std::vector<int64_t> record_ids;
int64_t index = TARGET_PARTITION * BATCH_ROW_COUNT + SEARCH_TARGET;
milvus_sdk::Utils::BuildVectors(index, index + 1, record_array, record_ids, TABLE_DIMENSION);
search_record_array.push_back(std::make_pair(record_ids[0], record_array[0]));
std::vector<milvus::Entity> entity_array;
std::vector<int64_t> entity_ids;
int64_t index = TARGET_PARTITION * BATCH_ENTITY_COUNT + SEARCH_TARGET;
milvus_sdk::Utils::BuildEntities(index, index + 1, entity_array, entity_ids, COLLECTION_DIMENSION);
search_entity_array.push_back(std::make_pair(entity_ids[0], entity_array[0]));
}
{ // search vectors
std::cout << "Search in correct partition" << std::endl;
std::vector<std::string> partition_tags = {std::to_string(TARGET_PARTITION)};
milvus::TopKQueryResult topk_query_result;
milvus_sdk::Utils::DoSearch(conn, TABLE_NAME, partition_tags, TOP_K, NPROBE, search_record_array,
milvus_sdk::Utils::DoSearch(conn, COLLECTION_NAME, partition_tags, TOP_K, NPROBE, search_entity_array,
topk_query_result);
std::cout << "Search in wrong partition" << std::endl;
partition_tags = {"0"};
milvus_sdk::Utils::DoSearch(conn, TABLE_NAME, partition_tags, TOP_K, NPROBE, search_record_array,
milvus_sdk::Utils::DoSearch(conn, COLLECTION_NAME, partition_tags, TOP_K, NPROBE, search_entity_array,
topk_query_result);
std::cout << "Search by regex matched partition tag" << std::endl;
partition_tags = {"\\d"};
milvus_sdk::Utils::DoSearch(conn, TABLE_NAME, partition_tags, TOP_K, NPROBE, search_record_array,
milvus_sdk::Utils::DoSearch(conn, COLLECTION_NAME, partition_tags, TOP_K, NPROBE, search_entity_array,
topk_query_result);
}
......@@ -166,57 +176,42 @@ ClientTest::Test(const std::string& address, const std::string& port) {
std::cout << "CreateIndex function call status: " << stat.message() << std::endl;
milvus::IndexParam index2;
stat = conn->DescribeIndex(TABLE_NAME, index2);
stat = conn->DescribeIndex(COLLECTION_NAME, index2);
std::cout << "DescribeIndex function call status: " << stat.message() << std::endl;
milvus_sdk::Utils::PrintIndexParam(index2);
}
{ // table row count
int64_t row_count = 0;
stat = conn->CountTable(TABLE_NAME, row_count);
std::cout << TABLE_NAME << "(" << row_count << " rows)" << std::endl;
}
{ // get table information
milvus::TableInfo table_info;
stat = conn->ShowTableInfo(TABLE_NAME, table_info);
milvus_sdk::Utils::PrintTableInfo(table_info);
std::cout << "ShowTableInfo function call status: " << stat.message() << std::endl;
}
ShowCollectionInfo(conn);
{ // drop partition
milvus::PartitionParam param1 = {TABLE_NAME, std::to_string(TARGET_PARTITION)};
milvus::PartitionParam param1 = {COLLECTION_NAME, std::to_string(TARGET_PARTITION)};
milvus_sdk::Utils::PrintPartitionParam(param1);
stat = conn->DropPartition(param1);
std::cout << "DropPartition function call status: " << stat.message() << std::endl;
}
{ // table row count
int64_t row_count = 0;
stat = conn->CountTable(TABLE_NAME, row_count);
std::cout << TABLE_NAME << "(" << row_count << " rows)" << std::endl;
}
CountCollection(conn);
{ // search vectors
std::cout << "Search in whole table" << std::endl;
{ // search vectors, will get search error since we delete a partition
std::cout << "Search in whole collection after delete one partition" << std::endl;
std::vector<std::string> partition_tags;
milvus::TopKQueryResult topk_query_result;
milvus_sdk::Utils::DoSearch(conn, TABLE_NAME, partition_tags, TOP_K, NPROBE, search_record_array,
milvus_sdk::Utils::DoSearch(conn, COLLECTION_NAME, partition_tags, TOP_K, NPROBE, search_entity_array,
topk_query_result);
}
{ // drop index
stat = conn->DropIndex(TABLE_NAME);
stat = conn->DropIndex(COLLECTION_NAME);
std::cout << "DropIndex function call status: " << stat.message() << std::endl;
int64_t row_count = 0;
stat = conn->CountTable(TABLE_NAME, row_count);
std::cout << TABLE_NAME << "(" << row_count << " rows)" << std::endl;
int64_t entity_count = 0;
stat = conn->CountCollection(COLLECTION_NAME, entity_count);
std::cout << COLLECTION_NAME << "(" << entity_count << " entities)" << std::endl;
}
{ // drop table
stat = conn->DropTable(TABLE_NAME);
std::cout << "DropTable function call status: " << stat.message() << std::endl;
{ // drop collection
stat = conn->DropCollection(COLLECTION_NAME);
std::cout << "DropCollection function call status: " << stat.message() << std::endl;
}
milvus::Connection::Destroy(conn);
......
......@@ -19,20 +19,19 @@
#include <utility>
#include <vector>
namespace {
const char* TABLE_NAME = milvus_sdk::Utils::GenTableName().c_str();
const char* COLLECTION_NAME = milvus_sdk::Utils::GenCollectionName().c_str();
constexpr int64_t TABLE_DIMENSION = 512;
constexpr int64_t TABLE_INDEX_FILE_SIZE = 1024;
constexpr milvus::MetricType TABLE_METRIC_TYPE = milvus::MetricType::L2;
constexpr int64_t BATCH_ROW_COUNT = 100000;
constexpr int64_t COLLECTION_DIMENSION = 512;
constexpr int64_t COLLECTION_INDEX_FILE_SIZE = 1024;
constexpr milvus::MetricType COLLECTION_METRIC_TYPE = milvus::MetricType::L2;
constexpr int64_t BATCH_ENTITY_COUNT = 100000;
constexpr int64_t NQ = 5;
constexpr int64_t TOP_K = 10;
constexpr int64_t NPROBE = 32;
constexpr int64_t SEARCH_TARGET = 5000; // change this value, result is different
constexpr int64_t ADD_VECTOR_LOOP = 5;
constexpr int64_t ADD_ENTITY_LOOP = 5;
constexpr milvus::IndexType INDEX_TYPE = milvus::IndexType::IVFSQ8;
constexpr int32_t NLIST = 16384;
......@@ -63,191 +62,201 @@ ClientTest::ShowSdkVersion() {
}
void
ClientTest::ShowTables(std::vector<std::string>& tables) {
milvus::Status stat = conn_->ShowTables(tables);
std::cout << "ShowTables function call status: " << stat.message() << std::endl;
std::cout << "All tables: " << std::endl;
for (auto& table : tables) {
int64_t row_count = 0;
stat = conn_->CountTable(table, row_count);
std::cout << "\t" << table << "(" << row_count << " rows)" << std::endl;
ClientTest::ShowCollections(std::vector<std::string>& collection_array) {
milvus::Status stat = conn_->ShowCollections(collection_array);
std::cout << "ShowCollections function call status: " << stat.message() << std::endl;
std::cout << "All collections: " << std::endl;
for (auto& collection : collection_array) {
int64_t entity_count = 0;
stat = conn_->CountCollection(collection, entity_count);
std::cout << "\t" << collection << "(" << entity_count << " entities)" << std::endl;
}
}
void
ClientTest::CreateTable(const std::string& table_name, int64_t dim, milvus::MetricType type) {
milvus::TableSchema tb_schema = {table_name, dim, TABLE_INDEX_FILE_SIZE, type};
milvus::Status stat = conn_->CreateTable(tb_schema);
std::cout << "CreateTable function call status: " << stat.message() << std::endl;
milvus_sdk::Utils::PrintTableSchema(tb_schema);
ClientTest::CreateCollection(const std::string& collection_name, int64_t dim, milvus::MetricType type) {
milvus::CollectionParam collection_param = {collection_name, dim, COLLECTION_INDEX_FILE_SIZE, type};
milvus::Status stat = conn_->CreateCollection(collection_param);
std::cout << "CreateCollection function call status: " << stat.message() << std::endl;
milvus_sdk::Utils::PrintCollectionParam(collection_param);
bool has_table = conn_->HasTable(tb_schema.table_name);
bool has_table = conn_->HasCollection(collection_param.collection_name);
if (has_table) {
std::cout << "Table is created" << std::endl;
std::cout << "Collection is created" << std::endl;
}
}
void
ClientTest::DescribeTable(const std::string& table_name) {
milvus::TableSchema tb_schema;
milvus::Status stat = conn_->DescribeTable(table_name, tb_schema);
std::cout << "DescribeTable function call status: " << stat.message() << std::endl;
milvus_sdk::Utils::PrintTableSchema(tb_schema);
ClientTest::DescribeCollection(const std::string& collection_name) {
milvus::CollectionParam collection_param;
milvus::Status stat = conn_->DescribeCollection(collection_name, collection_param);
std::cout << "DescribeCollection function call status: " << stat.message() << std::endl;
milvus_sdk::Utils::PrintCollectionParam(collection_param);
}
void
ClientTest::InsertVectors(const std::string& table_name, int64_t dim) {
for (int i = 0; i < ADD_VECTOR_LOOP; i++) {
std::vector<milvus::RowRecord> record_array;
ClientTest::InsertEntities(const std::string& collection_name, int64_t dim) {
for (int i = 0; i < ADD_ENTITY_LOOP; i++) {
std::vector<milvus::Entity> entity_array;
std::vector<int64_t> record_ids;
int64_t begin_index = i * BATCH_ROW_COUNT;
int64_t begin_index = i * BATCH_ENTITY_COUNT;
{ // generate vectors
milvus_sdk::TimeRecorder rc("Build vectors No." + std::to_string(i));
milvus_sdk::Utils::BuildVectors(begin_index, begin_index + BATCH_ROW_COUNT, record_array, record_ids, dim);
milvus_sdk::TimeRecorder rc("Build entities No." + std::to_string(i));
milvus_sdk::Utils::BuildEntities(begin_index,
begin_index + BATCH_ENTITY_COUNT,
entity_array,
record_ids,
dim);
}
std::string title = "Insert " + std::to_string(record_array.size()) + " vectors No." + std::to_string(i);
std::string title = "Insert " + std::to_string(entity_array.size()) + " entities No." + std::to_string(i);
milvus_sdk::TimeRecorder rc(title);
milvus::Status stat = conn_->Insert(table_name, "", record_array, record_ids);
std::cout << "InsertVector function call status: " << stat.message() << std::endl;
milvus::Status stat = conn_->Insert(collection_name, "", entity_array, record_ids);
std::cout << "InsertEntities function call status: " << stat.message() << std::endl;
std::cout << "Returned id array count: " << record_ids.size() << std::endl;
}
}
void
ClientTest::BuildSearchVectors(int64_t nq, int64_t dim) {
search_record_array_.clear();
ClientTest::BuildSearchEntities(int64_t nq, int64_t dim) {
search_entity_array_.clear();
search_id_array_.clear();
for (int64_t i = 0; i < nq; i++) {
std::vector<milvus::RowRecord> record_array;
std::vector<milvus::Entity> entity_array;
std::vector<int64_t> record_ids;
int64_t index = i * BATCH_ROW_COUNT + SEARCH_TARGET;
milvus_sdk::Utils::BuildVectors(index, index + 1, record_array, record_ids, dim);
search_record_array_.push_back(std::make_pair(record_ids[0], record_array[0]));
int64_t index = i * BATCH_ENTITY_COUNT + SEARCH_TARGET;
milvus_sdk::Utils::BuildEntities(index, index + 1, entity_array, record_ids, dim);
search_entity_array_.push_back(std::make_pair(record_ids[0], entity_array[0]));
search_id_array_.push_back(record_ids[0]);
}
}
void
ClientTest::Flush(const std::string& table_name) {
ClientTest::Flush(const std::string& collection_name) {
milvus_sdk::TimeRecorder rc("Flush");
milvus::Status stat = conn_->FlushTable(table_name);
std::cout << "FlushTable function call status: " << stat.message() << std::endl;
milvus::Status stat = conn_->FlushCollection(collection_name);
std::cout << "FlushCollection function call status: " << stat.message() << std::endl;
}
void
ClientTest::ShowTableInfo(const std::string& table_name) {
milvus::TableInfo table_info;
milvus::Status stat = conn_->ShowTableInfo(table_name, table_info);
milvus_sdk::Utils::PrintTableInfo(table_info);
std::cout << "ShowTableInfo function call status: " << stat.message() << std::endl;
ClientTest::ShowCollectionInfo(const std::string& collection_name) {
milvus::CollectionInfo collection_info;
milvus::Status stat = conn_->ShowCollectionInfo(collection_name, collection_info);
milvus_sdk::Utils::PrintCollectionInfo(collection_info);
std::cout << "ShowCollectionInfo function call status: " << stat.message() << std::endl;
}
void
ClientTest::GetVectorById(const std::string& table_name, int64_t id) {
milvus::RowRecord vector_data;
milvus::Status stat = conn_->GetVectorByID(table_name, id, vector_data);
std::cout << "The vector " << id << " has " << vector_data.float_data.size() << " float elements" << std::endl;
std::cout << "GetVectorByID function call status: " << stat.message() << std::endl;
ClientTest::GetEntityById(const std::string& collection_name, int64_t id) {
milvus::Entity entity;
milvus::Status stat = conn_->GetEntityByID(collection_name, id, entity);
std::cout << "The entity " << id << " has " << entity.float_data.size() << " float elements" << std::endl;
std::cout << "GetEntityById function call status: " << stat.message() << std::endl;
}
void
ClientTest::SearchVectors(const std::string& table_name, int64_t topk, int64_t nprobe) {
ClientTest::SearchEntities(const std::string& collection_name, int64_t topk, int64_t nprobe) {
std::vector<std::string> partition_tags;
milvus::TopKQueryResult topk_query_result;
milvus_sdk::Utils::DoSearch(conn_, table_name, partition_tags, topk, nprobe, search_record_array_,
milvus_sdk::Utils::DoSearch(conn_, collection_name, partition_tags, topk, nprobe, search_entity_array_,
topk_query_result);
}
void
ClientTest::CreateIndex(const std::string& table_name, milvus::IndexType type, int64_t nlist) {
ClientTest::CreateIndex(const std::string& collection_name, milvus::IndexType type, int64_t nlist) {
milvus_sdk::TimeRecorder rc("Create index");
std::cout << "Wait until create all index done" << std::endl;
JSON json_params = {{"nlist", nlist}};
milvus::IndexParam index1 = {table_name, type, json_params.dump()};
milvus::IndexParam index1 = {collection_name, type, json_params.dump()};
milvus_sdk::Utils::PrintIndexParam(index1);
milvus::Status stat = conn_->CreateIndex(index1);
std::cout << "CreateIndex function call status: " << stat.message() << std::endl;
milvus::IndexParam index2;
stat = conn_->DescribeIndex(table_name, index2);
stat = conn_->DescribeIndex(collection_name, index2);
std::cout << "DescribeIndex function call status: " << stat.message() << std::endl;
milvus_sdk::Utils::PrintIndexParam(index2);
}
void
ClientTest::PreloadTable(const std::string& table_name) {
milvus::Status stat = conn_->PreloadTable(table_name);
std::cout << "PreloadTable function call status: " << stat.message() << std::endl;
ClientTest::PreloadCollection(const std::string& collection_name) {
milvus::Status stat = conn_->PreloadCollection(collection_name);
std::cout << "PreloadCollection function call status: " << stat.message() << std::endl;
}
void
ClientTest::DeleteByIds(const std::string& table_name, const std::vector<int64_t>& id_array) {
milvus::Status stat = conn_->DeleteByID(table_name, id_array);
ClientTest::DeleteByIds(const std::string& collection_name, const std::vector<int64_t>& id_array) {
std::cout << "Delete entity: ";
for (auto id : id_array) {
std::cout << "\t" << id;
}
std::cout << std::endl;
milvus::Status stat = conn_->DeleteByID(collection_name, id_array);
std::cout << "DeleteByID function call status: " << stat.message() << std::endl;
{
milvus_sdk::TimeRecorder rc("Flush");
stat = conn_->FlushTable(table_name);
std::cout << "FlushTable function call status: " << stat.message() << std::endl;
stat = conn_->FlushCollection(collection_name);
std::cout << "FlushCollection function call status: " << stat.message() << std::endl;
}
{
// compact table
milvus_sdk::TimeRecorder rc1("Compact");
stat = conn_->CompactTable(table_name);
std::cout << "CompactTable function call status: " << stat.message() << std::endl;
stat = conn_->CompactCollection(collection_name);
std::cout << "CompactCollection function call status: " << stat.message() << std::endl;
}
}
void
ClientTest::DropIndex(const std::string& table_name) {
milvus::Status stat = conn_->DropIndex(table_name);
ClientTest::DropIndex(const std::string& collection_name) {
milvus::Status stat = conn_->DropIndex(collection_name);
std::cout << "DropIndex function call status: " << stat.message() << std::endl;
int64_t row_count = 0;
stat = conn_->CountTable(table_name, row_count);
std::cout << table_name << "(" << row_count << " rows)" << std::endl;
stat = conn_->CountCollection(collection_name, row_count);
std::cout << collection_name << "(" << row_count << " rows)" << std::endl;
}
void
ClientTest::DropTable(const std::string& table_name) {
milvus::Status stat = conn_->DropTable(table_name);
std::cout << "DropTable function call status: " << stat.message() << std::endl;
ClientTest::DropCollection(const std::string& collection_name) {
milvus::Status stat = conn_->DropCollection(collection_name);
std::cout << "DropCollection function call status: " << stat.message() << std::endl;
}
void
ClientTest::Test() {
std::string table_name = TABLE_NAME;
int64_t dim = TABLE_DIMENSION;
milvus::MetricType metric_type = TABLE_METRIC_TYPE;
std::string collection_name = COLLECTION_NAME;
int64_t dim = COLLECTION_DIMENSION;
milvus::MetricType metric_type = COLLECTION_METRIC_TYPE;
ShowServerVersion();
ShowSdkVersion();
std::vector<std::string> table_array;
ShowTables(table_array);
ShowCollections(table_array);
CreateTable(table_name, dim, metric_type);
DescribeTable(table_name);
CreateCollection(collection_name, dim, metric_type);
DescribeCollection(collection_name);
InsertVectors(table_name, dim);
BuildSearchVectors(NQ, dim);
Flush(table_name);
ShowTableInfo(table_name);
InsertEntities(collection_name, dim);
BuildSearchEntities(NQ, dim);
Flush(collection_name);
ShowCollectionInfo(collection_name);
GetVectorById(table_name, search_id_array_[0]);
SearchVectors(table_name, TOP_K, NPROBE);
GetEntityById(collection_name, search_id_array_[0]);
SearchEntities(collection_name, TOP_K, NPROBE);
CreateIndex(table_name, INDEX_TYPE, NLIST);
ShowTableInfo(table_name);
CreateIndex(collection_name, INDEX_TYPE, NLIST);
ShowCollectionInfo(collection_name);
PreloadTable(table_name);
PreloadCollection(collection_name);
std::vector<int64_t> delete_ids = {search_id_array_[0], search_id_array_[1]};
DeleteByIds(table_name, delete_ids);
SearchVectors(table_name, TOP_K, NPROBE);
DeleteByIds(collection_name, delete_ids);
SearchEntities(collection_name, TOP_K, NPROBE); // this line get two search error since we delete two entities
DropIndex(table_name);
DropTable(table_name);
DropIndex(collection_name);
DropCollection(collection_name);
}
......@@ -34,49 +34,49 @@ class ClientTest {
ShowSdkVersion();
void
ShowTables(std::vector<std::string>&);
ShowCollections(std::vector<std::string>&);
void
CreateTable(const std::string&, int64_t, milvus::MetricType);
CreateCollection(const std::string&, int64_t, milvus::MetricType);
void
DescribeTable(const std::string&);
DescribeCollection(const std::string&);
void
InsertVectors(const std::string&, int64_t);
InsertEntities(const std::string&, int64_t);
void
BuildSearchVectors(int64_t, int64_t);
BuildSearchEntities(int64_t, int64_t);
void
Flush(const std::string&);
void
ShowTableInfo(const std::string&);
ShowCollectionInfo(const std::string&);
void
GetVectorById(const std::string&, int64_t);
GetEntityById(const std::string&, int64_t);
void
SearchVectors(const std::string&, int64_t, int64_t);
SearchEntities(const std::string&, int64_t, int64_t);
void
CreateIndex(const std::string&, milvus::IndexType, int64_t);
void
PreloadTable(const std::string&);
PreloadCollection(const std::string&);
void
DeleteByIds(const std::string&, const std::vector<int64_t>&);
DeleteByIds(const std::string&, const std::vector<int64_t>& id_array);
void
DropIndex(const std::string&);
void
DropTable(const std::string&);
DropCollection(const std::string&);
private:
std::shared_ptr<milvus::Connection> conn_;
std::vector<std::pair<int64_t, milvus::RowRecord>> search_record_array_;
std::vector<std::pair<int64_t, milvus::Entity>> search_entity_array_;
std::vector<int64_t> search_id_array_;
};
......@@ -64,8 +64,8 @@ Utils::Sleep(int seconds) {
}
const std::string&
Utils::GenTableName() {
static std::string s_id("tbl_" + CurrentTime());
Utils::GenCollectionName() {
static std::string s_id("C_" + CurrentTime());
return s_id;
}
......@@ -97,19 +97,19 @@ Utils::IndexTypeName(const milvus::IndexType& index_type) {
}
void
Utils::PrintTableSchema(const milvus::TableSchema& tb_schema) {
Utils::PrintCollectionParam(const milvus::CollectionParam& collection_param) {
BLOCK_SPLITER
std::cout << "Table name: " << tb_schema.table_name << std::endl;
std::cout << "Table dimension: " << tb_schema.dimension << std::endl;
std::cout << "Table index file size: " << tb_schema.index_file_size << std::endl;
std::cout << "Table metric type: " << MetricTypeName(tb_schema.metric_type) << std::endl;
std::cout << "Collection name: " << collection_param.collection_name << std::endl;
std::cout << "Collection dimension: " << collection_param.dimension << std::endl;
std::cout << "Collection index file size: " << collection_param.index_file_size << std::endl;
std::cout << "Collection metric type: " << MetricTypeName(collection_param.metric_type) << std::endl;
BLOCK_SPLITER
}
void
Utils::PrintPartitionParam(const milvus::PartitionParam& partition_param) {
BLOCK_SPLITER
std::cout << "Table name: " << partition_param.table_name << std::endl;
std::cout << "Collection name: " << partition_param.collection_name << std::endl;
std::cout << "Partition tag: " << partition_param.partition_tag << std::endl;
BLOCK_SPLITER
}
......@@ -117,40 +117,40 @@ Utils::PrintPartitionParam(const milvus::PartitionParam& partition_param) {
void
Utils::PrintIndexParam(const milvus::IndexParam& index_param) {
BLOCK_SPLITER
std::cout << "Index table name: " << index_param.table_name << std::endl;
std::cout << "Index collection name: " << index_param.collection_name << std::endl;
std::cout << "Index type: " << IndexTypeName(index_param.index_type) << std::endl;
std::cout << "Index extra_params: " << index_param.extra_params << std::endl;
BLOCK_SPLITER
}
void
Utils::BuildVectors(int64_t from, int64_t to, std::vector<milvus::RowRecord>& vector_record_array,
std::vector<int64_t>& record_ids, int64_t dimension) {
Utils::BuildEntities(int64_t from, int64_t to, std::vector<milvus::Entity>& entity_array,
std::vector<int64_t>& entity_ids, int64_t dimension) {
if (to <= from) {
return;
}
vector_record_array.clear();
record_ids.clear();
entity_array.clear();
entity_ids.clear();
for (int64_t k = from; k < to; k++) {
milvus::RowRecord record;
record.float_data.resize(dimension);
milvus::Entity entity;
entity.float_data.resize(dimension);
for (int64_t i = 0; i < dimension; i++) {
record.float_data[i] = (float)(k % (i + 1));
entity.float_data[i] = (float)(k % (i + 1));
}
vector_record_array.emplace_back(record);
record_ids.push_back(k);
entity_array.emplace_back(entity);
entity_ids.push_back(k);
}
}
void
Utils::PrintSearchResult(const std::vector<std::pair<int64_t, milvus::RowRecord>>& search_record_array,
Utils::PrintSearchResult(const std::vector<std::pair<int64_t, milvus::Entity>>& entity_array,
const milvus::TopKQueryResult& topk_query_result) {
BLOCK_SPLITER
std::cout << "Returned result count: " << topk_query_result.size() << std::endl;
if (topk_query_result.size() != search_record_array.size()) {
if (topk_query_result.size() != entity_array.size()) {
std::cout << "ERROR: Returned result count not equal nq" << std::endl;
return;
}
......@@ -158,8 +158,8 @@ Utils::PrintSearchResult(const std::vector<std::pair<int64_t, milvus::RowRecord>
for (size_t i = 0; i < topk_query_result.size(); i++) {
const milvus::QueryResult& one_result = topk_query_result[i];
size_t topk = one_result.ids.size();
auto search_id = search_record_array[i].first;
std::cout << "No." << i << " vector " << search_id << " top " << topk << " search result:" << std::endl;
auto search_id = entity_array[i].first;
std::cout << "No." << i << " entity " << search_id << " top " << topk << " search result:" << std::endl;
for (size_t j = 0; j < topk; j++) {
std::cout << "\t" << one_result.ids[j] << "\t" << one_result.distances[j] << std::endl;
}
......@@ -168,13 +168,13 @@ Utils::PrintSearchResult(const std::vector<std::pair<int64_t, milvus::RowRecord>
}
void
Utils::CheckSearchResult(const std::vector<std::pair<int64_t, milvus::RowRecord>>& search_record_array,
Utils::CheckSearchResult(const std::vector<std::pair<int64_t, milvus::Entity>>& entity_array,
const milvus::TopKQueryResult& topk_query_result) {
BLOCK_SPLITER
size_t nq = topk_query_result.size();
for (size_t i = 0; i < nq; i++) {
const milvus::QueryResult& one_result = topk_query_result[i];
auto search_id = search_record_array[i].first;
auto search_id = entity_array[i].first;
uint64_t match_index = one_result.ids.size();
for (uint64_t index = 0; index < one_result.ids.size(); index++) {
......@@ -195,15 +195,15 @@ Utils::CheckSearchResult(const std::vector<std::pair<int64_t, milvus::RowRecord>
}
void
Utils::DoSearch(std::shared_ptr<milvus::Connection> conn, const std::string& table_name,
Utils::DoSearch(std::shared_ptr<milvus::Connection> conn, const std::string& collection_name,
const std::vector<std::string>& partition_tags, int64_t top_k, int64_t nprobe,
const std::vector<std::pair<int64_t, milvus::RowRecord>>& search_record_array,
const std::vector<std::pair<int64_t, milvus::Entity>>& entity_array,
milvus::TopKQueryResult& topk_query_result) {
topk_query_result.clear();
std::vector<milvus::RowRecord> record_array;
for (auto& pair : search_record_array) {
record_array.push_back(pair.second);
std::vector<milvus::Entity> temp_entity_array;
for (auto& pair : entity_array) {
temp_entity_array.push_back(pair.second);
}
{
......@@ -211,28 +211,33 @@ Utils::DoSearch(std::shared_ptr<milvus::Connection> conn, const std::string& tab
JSON json_params = {{"nprobe", nprobe}};
milvus_sdk::TimeRecorder rc("search");
milvus::Status stat =
conn->Search(table_name, partition_tags, record_array, top_k, json_params.dump(), topk_query_result);
std::cout << "SearchVector function call status: " << stat.message() << std::endl;
conn->Search(collection_name,
partition_tags,
temp_entity_array,
top_k,
json_params.dump(),
topk_query_result);
std::cout << "Search function call status: " << stat.message() << std::endl;
BLOCK_SPLITER
}
PrintSearchResult(search_record_array, topk_query_result);
CheckSearchResult(search_record_array, topk_query_result);
PrintSearchResult(entity_array, topk_query_result);
CheckSearchResult(entity_array, topk_query_result);
}
void
PrintPartitionStat(const milvus::PartitionStat& partition_stat) {
std::cout << "\tPartition " << partition_stat.tag << " row count: " << partition_stat.row_count << std::endl;
std::cout << "\tPartition " << partition_stat.tag << " entity count: " << partition_stat.row_count << std::endl;
for (auto& seg_stat : partition_stat.segments_stat) {
std::cout << "\t\tsegment " << seg_stat.segment_name << " row count: " << seg_stat.row_count
std::cout << "\t\tsegment " << seg_stat.segment_name << " entity count: " << seg_stat.row_count
<< " index: " << seg_stat.index_name << " data size: " << seg_stat.data_size << std::endl;
}
}
void
Utils::PrintTableInfo(const milvus::TableInfo& info) {
Utils::PrintCollectionInfo(const milvus::CollectionInfo& info) {
BLOCK_SPLITER
std::cout << "Table " << " total row count: " << info.total_row_count << std::endl;
std::cout << "Collection " << " total entity count: " << info.total_row_count << std::endl;
for (const milvus::PartitionStat& partition_stat : info.partitions_stat) {
PrintPartitionStat(partition_stat);
}
......
......@@ -32,7 +32,7 @@ class Utils {
CurrentTmDate(int64_t offset_day = 0);
static const std::string&
GenTableName();
GenCollectionName();
static void
Sleep(int seconds);
......@@ -44,7 +44,7 @@ class Utils {
IndexTypeName(const milvus::IndexType& index_type);
static void
PrintTableSchema(const milvus::TableSchema& tb_schema);
PrintCollectionParam(const milvus::CollectionParam& collection_param);
static void
PrintPartitionParam(const milvus::PartitionParam& partition_param);
......@@ -53,25 +53,25 @@ class Utils {
PrintIndexParam(const milvus::IndexParam& index_param);
static void
BuildVectors(int64_t from, int64_t to, std::vector<milvus::RowRecord>& vector_record_array,
std::vector<int64_t>& record_ids, int64_t dimension);
BuildEntities(int64_t from, int64_t to, std::vector<milvus::Entity>& entity_array,
std::vector<int64_t>& entity_ids, int64_t dimension);
static void
PrintSearchResult(const std::vector<std::pair<int64_t, milvus::RowRecord>>& search_record_array,
PrintSearchResult(const std::vector<std::pair<int64_t, milvus::Entity>>& entity_array,
const milvus::TopKQueryResult& topk_query_result);
static void
CheckSearchResult(const std::vector<std::pair<int64_t, milvus::RowRecord>>& search_record_array,
CheckSearchResult(const std::vector<std::pair<int64_t, milvus::Entity>>& entity_array,
const milvus::TopKQueryResult& topk_query_result);
static void
DoSearch(std::shared_ptr<milvus::Connection> conn, const std::string& table_name,
DoSearch(std::shared_ptr<milvus::Connection> conn, const std::string& collection_name,
const std::vector<std::string>& partition_tags, int64_t top_k, int64_t nprobe,
const std::vector<std::pair<int64_t, milvus::RowRecord>>& search_record_array,
const std::vector<std::pair<int64_t, milvus::Entity>>& entity_array,
milvus::TopKQueryResult& topk_query_result);
static void
PrintTableInfo(const milvus::TableInfo& info);
PrintCollectionInfo(const milvus::CollectionInfo& collection_info);
};
} // namespace milvus_sdk
此差异已折叠。
......@@ -24,7 +24,7 @@ class ClientProxy : public Connection {
public:
// Implementations of the Connection interface
Status
Connect(const ConnectParam& param) override;
Connect(const ConnectParam& connect_param) override;
Status
Connect(const std::string& uri) override;
......@@ -35,90 +35,92 @@ class ClientProxy : public Connection {
Status
Disconnect() override;
std::string
ClientVersion() const override;
std::string
ServerVersion() const override;
std::string
ServerStatus() const override;
Status
GetConfig(const std::string& node_name, std::string& value) const override;
Status
SetConfig(const std::string& node_name, const std::string& value) const override;
Status
CreateTable(const TableSchema& param) override;
CreateCollection(const CollectionParam& param) override;
bool
HasTable(const std::string& table_name) override;
HasCollection(const std::string& collection_name) override;
Status
DropTable(const std::string& table_name) override;
DropCollection(const std::string& collection_name) override;
Status
CreateIndex(const IndexParam& index_param) override;
Status
Insert(const std::string& table_name, const std::string& partition_tag, const std::vector<RowRecord>& record_array,
Insert(const std::string& collection_name,
const std::string& partition_tag,
const std::vector<Entity>& entity_array,
std::vector<int64_t>& id_array) override;
Status
GetVectorByID(const std::string& table_name, int64_t vector_id, RowRecord& vector_data) override;
GetEntityByID(const std::string& collection_name, int64_t entity_id, Entity& entity_data) override;
Status
GetIDsInSegment(const std::string& table_name, const std::string& segment_name,
GetIDsInSegment(const std::string& collection_name, const std::string& segment_name,
std::vector<int64_t>& id_array) override;
Status
Search(const std::string& table_name, const std::vector<std::string>& partition_tag_array,
const std::vector<RowRecord>& query_record_array, int64_t topk, const std::string& extra_params,
TopKQueryResult& topk_query_result) override;
Search(const std::string& collection_name, const std::vector<std::string>& partition_tag_array,
const std::vector<Entity>& entity_array, int64_t topk,
const std::string& extra_params, TopKQueryResult& topk_query_result) override;
Status
DescribeTable(const std::string& table_name, TableSchema& table_schema) override;
DescribeCollection(const std::string& collection_name, CollectionParam& collection_schema) override;
Status
CountTable(const std::string& table_name, int64_t& row_count) override;
CountCollection(const std::string& collection_name, int64_t& entity_count) override;
Status
ShowTables(std::vector<std::string>& table_array) override;
ShowCollections(std::vector<std::string>& collection_array) override;
Status
ShowTableInfo(const std::string& table_name, TableInfo& table_info) override;
std::string
ClientVersion() const override;
std::string
ServerVersion() const override;
std::string
ServerStatus() const override;
ShowCollectionInfo(const std::string& collection_name, CollectionInfo& collection_info) override;
Status
DeleteByID(const std::string& table_name, const std::vector<int64_t>& id_array) override;
DeleteByID(const std::string& collection_name, const std::vector<int64_t>& id_array) override;
Status
PreloadTable(const std::string& table_name) const override;
PreloadCollection(const std::string& collection_name) const override;
Status
DescribeIndex(const std::string& table_name, IndexParam& index_param) const override;
DescribeIndex(const std::string& collection_name, IndexParam& index_param) const override;
Status
DropIndex(const std::string& table_name) const override;
DropIndex(const std::string& collection_name) const override;
Status
CreatePartition(const PartitionParam& partition_param) override;
Status
ShowPartitions(const std::string& table_name, PartitionTagList& partition_tag_array) const override;
ShowPartitions(const std::string& collection_name, PartitionTagList& partition_tag_array) const override;
Status
DropPartition(const PartitionParam& partition_param) override;
Status
GetConfig(const std::string& node_name, std::string& value) const override;
Status
SetConfig(const std::string& node_name, const std::string& value) const override;
Status
FlushTable(const std::string& table_name) override;
FlushCollection(const std::string& collection_name) override;
Status
Flush() override;
Status
CompactTable(const std::string& table_name) override;
CompactCollection(const std::string& collection_name) override;
private:
std::shared_ptr<::grpc::Channel> channel_;
......
......@@ -84,11 +84,19 @@ using TopKQueryResult = std::vector<QueryResult>; ///< Topk query result
* @brief Index parameters
* Note: extra_params is extra parameters list, it must be json format
* For different index type, parameter list is different accordingly, for example:
* FLAT/IVFLAT/SQ8: "{nlist: '16384'}" nlist range:[1, 999999]
* IVFPQ: "{nlist: '16384', m: "12"}" nlist range:[1, 999999] m is decided by dim and have a couple of results.
* FLAT/IVFLAT/SQ8: "{nlist: '16384'}"
* ///< nlist range:[1, 999999]
* IVFPQ: "{nlist: '16384', m: "12"}"
* ///< nlist range:[1, 999999]
* ///< m is decided by dim and have a couple of results.
* NSG: "{search_length: '45', out_degree:'50', candidate_pool_size:'300', "knng":'100'}"
* search_length range:[10, 300] out_degree range:[5, 300] candidate_pool_size range:[50, 1000] knng range:[5, 300]
* HNSW "{M: '16', efConstruction:'500'}" M range:[5, 48] efConstruction range:[topk, 4096]
* ///< search_length range:[10, 300]
* ///< out_degree range:[5, 300]
* ///< candidate_pool_size range:[50, 1000]
* ///< knng range:[5, 300]
* HNSW "{M: '16', efConstruction:'500'}"
* ///< M range:[5, 48]
* ///< efConstruction range:[topk, 4096]
*/
struct IndexParam {
std::string collection_name; ///< Collection name for create index
......@@ -139,18 +147,18 @@ struct CollectionInfo {
class Connection {
public:
/**
* @brief CreateConnection
* @brief Create connection
*
* Create a connection instance and return it's shared pointer
*
* @return Connection instance pointer
* @return connection instance pointer
*/
static std::shared_ptr<Connection>
Create();
/**
* @brief DestroyConnection
* @brief Destroy connection
*
* Destroy the connection instance
*
......@@ -174,7 +182,7 @@ class Connection {
*/
virtual Status
Connect(const ConnectParam& param) = 0;
Connect(const ConnectParam& connect_param) = 0;
/**
* @brief Connect
......@@ -190,7 +198,7 @@ class Connection {
Connect(const std::string& uri) = 0;
/**
* @brief connected
* @brief Connected
*
* This method is used to test whether server is connected.
*
......@@ -210,7 +218,7 @@ class Connection {
Disconnect() = 0;
/**
* @brief Give the client version
* @brief Get the client version
*
* This method is used to give the client version.
*
......@@ -220,7 +228,7 @@ class Connection {
ClientVersion() const = 0;
/**
* @brief Give the server version
* @brief Get the server version
*
* This method is used to give the server version.
*
......@@ -229,6 +237,42 @@ class Connection {
virtual std::string
ServerVersion() const = 0;
/**
* @brief Get the server status
*
* This method is used to give the server status.
*
* @return Server status.
*/
virtual std::string
ServerStatus() const = 0;
/**
* @brief Get config method
*
* This method is used to set config.
*
* @param node_name, config node name.
* @param value, config value.
*
* @return Indicate if this operation is successful.
*/
virtual Status
GetConfig(const std::string& node_name, std::string& value) const = 0;
/**
* @brief Set config method
*
* This method is used to set config.
*
* @param node_name, config node name.
* @param value, config value.
*
* @return Indicate if this operation is successful.
*/
virtual Status
SetConfig(const std::string& node_name, const std::string& value) const = 0;
/**
* @brief Create collection method
*
......@@ -278,9 +322,9 @@ class Connection {
CreateIndex(const IndexParam& index_param) = 0;
/**
* @brief Insert entity to table
* @brief Insert entity to collection
*
* This method is used to insert vector array to table.
* This method is used to insert vector array to collection.
*
* @param collection_name, target collection's name.
* @param partition_tag, target partition's tag, keep empty if no partition specified.
......@@ -337,21 +381,24 @@ class Connection {
*
* @param collection_name, target collection's name.
* @param partition_tag_array, target partitions, keep empty if no partition specified.
* @param query_record_array, vectors to be queried.
* @param topk, how many similarity vectors will be returned.
* @param query_entity_array, vectors to be queried.
* @param topk, how many similarity entities will be returned.
* @param extra_params, extra search parameters according to different index type, must be json format.
* Note: extra_params is extra parameters list, it must be json format, for example:
* For different index type, parameter list is different accordingly
* FLAT/IVFLAT/SQ8/IVFPQ: "{nprobe: '32'}"
* ///< nprobe range:[1,999999]
* NSG: "{search_length:'100'}
* ///< search_length range:[10, 300]
* HNSW "{ef: '64'}
* ///< ef range:[k, 4096]
* @param topk_query_result, result array.
*
* @return Indicate if query is successful.
*/
virtual Status
Search(const std::string& table_name, const PartitionTagList& partition_tag_array,
const std::vector<Entity>& query_record_array, int64_t topk,
Search(const std::string& collection_name, const PartitionTagList& partition_tag_array,
const std::vector<Entity>& entity_array, int64_t topk,
const std::string& extra_params, TopKQueryResult& topk_query_result) = 0;
/**
......@@ -360,17 +407,17 @@ class Connection {
* This method is used to show collection information.
*
* @param collection_name, target collection's name.
* @param collection_schema, collection_schema is given when operation is successful.
* @param collection_param, collection_param is given when operation is successful.
*
* @return Indicate if this operation is successful.
*/
virtual Status
DescribeCollection(const std::string& collection_name, TableSchema& collection_schema) = 0;
DescribeCollection(const std::string& collection_name, CollectionParam& collection_param) = 0;
/**
* @brief Get collection row count
* @brief Get collection entity count
*
* This method is used to get collection row count.
* This method is used to get collection entity count.
*
* @param collection_name, target collection's name.
* @param entity_count, collection total entity count(including partitions).
......@@ -393,160 +440,121 @@ class Connection {
ShowCollections(std::vector<std::string>& collection_array) = 0;
/**
* @brief Show collections information
* @brief Show collection information
*
* This method is used to get detail information of a collections.
* This method is used to get detail information of a collection.
*
* @param collections_name, target collections's name.
* @param collections_info, target collections's information
* @param collection_name, target collection's name.
* @param collection_info, target collection's information
*
* @return Indicate if this operation is successful.
*/
virtual Status
ShowCollectionInfo(const std::string& collections_name, TableInfo& collections_info) = 0;
/**
* @brief Give the server status
*
* This method is used to give the server status.
*
* @return Server status.
*/
virtual std::string
ServerStatus() const = 0;
ShowCollectionInfo(const std::string& collection_name, CollectionInfo& collection_info) = 0;
/**
* [deprecated]
* @brief delete tables by vector id
* @brief Delete entity by id
*
* This method is used to delete table data by date range.
* This method is used to delete entity by id.
*
* @param table_name, target table's name.
* @param id_array, vector ids to deleted.
* @param collection_name, target collection's name.
* @param id_array, entity id array to be deleted.
*
* @return Indicate if this operation is successful.
*/
virtual Status
DeleteByID(const std::string& table_name, const std::vector<int64_t>& id_array) = 0;
DeleteByID(const std::string& collection_name, const std::vector<int64_t>& id_array) = 0;
/**
* @brief preload table
* @brief Preload collection
*
* This method is used to preload table
* This method is used to preload collection data into memory
*
* @param table_name
* @param collection_name, target collection's name.
*
* @return Indicate if this operation is successful.
*/
virtual Status
PreloadTable(const std::string& table_name) const = 0;
PreloadCollection(const std::string& collection_name) const = 0;
/**
* @brief describe index
* @brief Describe index
*
* This method is used to describe index
*
* @param table_name, target table's name.
* @param collection_name, target collection's name.
* @param index_param, returned index information.
*
* @return Indicate if this operation is successful.
*/
virtual Status
DescribeIndex(const std::string& table_name, IndexParam& index_param) const = 0;
DescribeIndex(const std::string& collection_name, IndexParam& index_param) const = 0;
/**
* @brief drop index
* @brief Drop index
*
* This method is used to drop index of table(and its partitions)
* This method is used to drop index of collection(and its partitions)
*
* @param table_name, target table's name.
* @param collection_name, target collection's name.
*
* @return Indicate if this operation is successful.
*/
virtual Status
DropIndex(const std::string& table_name) const = 0;
DropIndex(const std::string& collection_name) const = 0;
/**
* @brief Create partition method
*
* This method is used to create table partition
* This method is used to create collection's partition
*
* @param param, use to provide partition information to be created.
* @param partition_param, use to provide partition information to be created.
*
* @return Indicate if partition is created successfully
*/
virtual Status
CreatePartition(const PartitionParam& param) = 0;
CreatePartition(const PartitionParam& partition_param) = 0;
/**
* @brief Test table existence method
* @brief Show all partitions method
*
* This method is used to create table
* This method is used to show all partitions(return their tags)
*
* @param table_name, table name is going to be tested.
* @param partition_tag_array, partition tag array of the table.
* @param collection_name, target collection's name.
* @param partition_tag_array, partition tag array of the collection.
*
* @return Indicate if this operation is successful
*/
virtual Status
ShowPartitions(const std::string& table_name, PartitionTagList& partition_tag_array) const = 0;
ShowPartitions(const std::string& collection_name, PartitionTagList& partition_tag_array) const = 0;
/**
* @brief Delete partition method
*
* This method is used to delete table partition.
* This method is used to delete collection's partition.
*
* @param param, target partition to be deleted.
* NOTE: if param.table_name is empty, you must specify param.partition_name,
* else you can specify param.table_name and param.tag and let the param.partition_name be empty
* @param partition_param, target partition to be deleted.
*
* @return Indicate if partition is delete successfully.
*/
virtual Status
DropPartition(const PartitionParam& param) = 0;
DropPartition(const PartitionParam& partition_param) = 0;
/**
* @brief Get config method
* @brief Flush collection buffer into storage
*
* This method is used to set config.
*
* @param node_name, config node name.
* @param value, config value.
* This method is used to flush collection buffer into storage
*
* @return Indicate if this operation is successful.
*/
virtual Status
GetConfig(const std::string& node_name, std::string& value) const = 0;
/**
* @brief Set config method
*
* This method is used to set config.
*
* @param node_name, config node name.
* @param value, config value.
*
* @return Indicate if this operation is successful.
*/
virtual Status
SetConfig(const std::string& node_name, const std::string& value) const = 0;
/**
* @brief flush table buffer into storage
*
* This method is used to flush table buffer into storage
*
* @param table_name, target table's name.
* @param collection_name, target collection's name.
*
* @return Indicate if this operation is successful.
*/
virtual Status
FlushTable(const std::string& table_name) = 0;
FlushCollection(const std::string& collection_name) = 0;
/**
* @brief flush all buffer into storage
* @brief Flush all buffer into storage
*
* This method is used to all table buffer into storage
* This method is used to all collection buffer into storage
*
* @return Indicate if this operation is successful.
*/
......@@ -554,16 +562,16 @@ class Connection {
Flush() = 0;
/**
* @brief compact table, remove deleted vectors
* @brief Compact collection, permanently remove deleted vectors
*
* This method is used to compact table
* This method is used to compact collection
*
* @param table_name, target table's name.
* @param collection_name, target collection's name.
*
* @return Indicate if this operation is successful.
*/
virtual Status
CompactTable(const std::string& table_name) = 0;
CompactCollection(const std::string& collection_name) = 0;
};
} // namespace milvus
......@@ -56,128 +56,128 @@ ConnectionImpl::ClientVersion() const {
return client_proxy_->ClientVersion();
}
Status
ConnectionImpl::CreateTable(const TableSchema& param) {
return client_proxy_->CreateTable(param);
std::string
ConnectionImpl::ServerVersion() const {
return client_proxy_->ServerVersion();
}
bool
ConnectionImpl::HasTable(const std::string& table_name) {
return client_proxy_->HasTable(table_name);
std::string
ConnectionImpl::ServerStatus() const {
return client_proxy_->ServerStatus();
}
Status
ConnectionImpl::DropTable(const std::string& table_name) {
return client_proxy_->DropTable(table_name);
ConnectionImpl::GetConfig(const std::string& node_name, std::string& value) const {
return client_proxy_->GetConfig(node_name, value);
}
Status
ConnectionImpl::CreateIndex(const IndexParam& index_param) {
return client_proxy_->CreateIndex(index_param);
ConnectionImpl::SetConfig(const std::string& node_name, const std::string& value) const {
return client_proxy_->SetConfig(node_name, value);
}
Status
ConnectionImpl::Insert(const std::string& table_name, const std::string& partition_tag,
const std::vector<RowRecord>& record_array, std::vector<int64_t>& id_array) {
return client_proxy_->Insert(table_name, partition_tag, record_array, id_array);
ConnectionImpl::CreateCollection(const CollectionParam& param) {
return client_proxy_->CreateCollection(param);
}
Status
ConnectionImpl::GetVectorByID(const std::string& table_name, int64_t vector_id, RowRecord& vector_data) {
return client_proxy_->GetVectorByID(table_name, vector_id, vector_data);
bool
ConnectionImpl::HasCollection(const std::string& collection_name) {
return client_proxy_->HasCollection(collection_name);
}
Status
ConnectionImpl::GetIDsInSegment(const std::string& table_name, const std::string& segment_name,
std::vector<int64_t>& id_array) {
return client_proxy_->GetIDsInSegment(table_name, segment_name, id_array);
ConnectionImpl::DropCollection(const std::string& collection_name) {
return client_proxy_->DropCollection(collection_name);
}
Status
ConnectionImpl::Search(const std::string& table_name, const std::vector<std::string>& partition_tags,
const std::vector<RowRecord>& query_record_array, int64_t topk, const std::string& extra_params,
TopKQueryResult& topk_query_result) {
return client_proxy_->Search(table_name, partition_tags, query_record_array, topk, extra_params, topk_query_result);
ConnectionImpl::CreateIndex(const IndexParam& index_param) {
return client_proxy_->CreateIndex(index_param);
}
Status
ConnectionImpl::DescribeTable(const std::string& table_name, TableSchema& table_schema) {
return client_proxy_->DescribeTable(table_name, table_schema);
ConnectionImpl::Insert(const std::string& collection_name, const std::string& partition_tag,
const std::vector<Entity>& entity_array, std::vector<int64_t>& id_array) {
return client_proxy_->Insert(collection_name, partition_tag, entity_array, id_array);
}
Status
ConnectionImpl::CountTable(const std::string& table_name, int64_t& row_count) {
return client_proxy_->CountTable(table_name, row_count);
ConnectionImpl::GetEntityByID(const std::string& collection_name, int64_t entity_id, Entity& entity_data) {
return client_proxy_->GetEntityByID(collection_name, entity_id, entity_data);
}
Status
ConnectionImpl::ShowTables(std::vector<std::string>& table_array) {
return client_proxy_->ShowTables(table_array);
ConnectionImpl::GetIDsInSegment(const std::string& collection_name, const std::string& segment_name,
std::vector<int64_t>& id_array) {
return client_proxy_->GetIDsInSegment(collection_name, segment_name, id_array);
}
Status
ConnectionImpl::ShowTableInfo(const std::string& table_name, TableInfo& table_info) {
return client_proxy_->ShowTableInfo(table_name, table_info);
ConnectionImpl::Search(const std::string& collection_name, const std::vector<std::string>& partition_tags,
const std::vector<Entity>& entity_array, int64_t topk, const std::string& extra_params,
TopKQueryResult& topk_query_result) {
return client_proxy_->Search(collection_name, partition_tags, entity_array, topk, extra_params, topk_query_result);
}
std::string
ConnectionImpl::ServerVersion() const {
return client_proxy_->ServerVersion();
Status
ConnectionImpl::DescribeCollection(const std::string& collection_name, CollectionParam& collection_schema) {
return client_proxy_->DescribeCollection(collection_name, collection_schema);
}
std::string
ConnectionImpl::ServerStatus() const {
return client_proxy_->ServerStatus();
Status
ConnectionImpl::CountCollection(const std::string& collection_name, int64_t& row_count) {
return client_proxy_->CountCollection(collection_name, row_count);
}
Status
ConnectionImpl::DeleteByID(const std::string& table_name, const std::vector<int64_t>& id_array) {
return client_proxy_->DeleteByID(table_name, id_array);
ConnectionImpl::ShowCollections(std::vector<std::string>& collection_array) {
return client_proxy_->ShowCollections(collection_array);
}
Status
ConnectionImpl::PreloadTable(const std::string& table_name) const {
return client_proxy_->PreloadTable(table_name);
ConnectionImpl::ShowCollectionInfo(const std::string& collection_name, CollectionInfo& collection_info) {
return client_proxy_->ShowCollectionInfo(collection_name, collection_info);
}
Status
ConnectionImpl::DescribeIndex(const std::string& table_name, IndexParam& index_param) const {
return client_proxy_->DescribeIndex(table_name, index_param);
ConnectionImpl::DeleteByID(const std::string& collection_name, const std::vector<int64_t>& id_array) {
return client_proxy_->DeleteByID(collection_name, id_array);
}
Status
ConnectionImpl::DropIndex(const std::string& table_name) const {
return client_proxy_->DropIndex(table_name);
ConnectionImpl::PreloadCollection(const std::string& collection_name) const {
return client_proxy_->PreloadCollection(collection_name);
}
Status
ConnectionImpl::CreatePartition(const PartitionParam& param) {
return client_proxy_->CreatePartition(param);
ConnectionImpl::DescribeIndex(const std::string& collection_name, IndexParam& index_param) const {
return client_proxy_->DescribeIndex(collection_name, index_param);
}
Status
ConnectionImpl::ShowPartitions(const std::string& table_name, PartitionTagList& partition_array) const {
return client_proxy_->ShowPartitions(table_name, partition_array);
ConnectionImpl::DropIndex(const std::string& collection_name) const {
return client_proxy_->DropIndex(collection_name);
}
Status
ConnectionImpl::DropPartition(const PartitionParam& param) {
return client_proxy_->DropPartition(param);
ConnectionImpl::CreatePartition(const PartitionParam& partition_param) {
return client_proxy_->CreatePartition(partition_param);
}
Status
ConnectionImpl::GetConfig(const std::string& node_name, std::string& value) const {
return client_proxy_->GetConfig(node_name, value);
ConnectionImpl::ShowPartitions(const std::string& collection_name, PartitionTagList& partition_array) const {
return client_proxy_->ShowPartitions(collection_name, partition_array);
}
Status
ConnectionImpl::SetConfig(const std::string& node_name, const std::string& value) const {
return client_proxy_->SetConfig(node_name, value);
ConnectionImpl::DropPartition(const PartitionParam& partition_param) {
return client_proxy_->DropPartition(partition_param);
}
Status
ConnectionImpl::FlushTable(const std::string& Status) {
return client_proxy_->FlushTable(Status);
ConnectionImpl::FlushCollection(const std::string& Status) {
return client_proxy_->FlushCollection(Status);
}
Status
......@@ -186,8 +186,8 @@ ConnectionImpl::Flush() {
}
Status
ConnectionImpl::CompactTable(const std::string& table_name) {
return client_proxy_->CompactTable(table_name);
ConnectionImpl::CompactCollection(const std::string& collection_name) {
return client_proxy_->CompactCollection(collection_name);
}
} // namespace milvus
......@@ -26,7 +26,7 @@ class ConnectionImpl : public Connection {
// Implementations of the Connection interface
Status
Connect(const ConnectParam& param) override;
Connect(const ConnectParam& connect_param) override;
Status
Connect(const std::string& uri) override;
......@@ -37,90 +37,92 @@ class ConnectionImpl : public Connection {
Status
Disconnect() override;
std::string
ClientVersion() const override;
std::string
ServerVersion() const override;
std::string
ServerStatus() const override;
Status
GetConfig(const std::string& node_name, std::string& value) const override;
Status
SetConfig(const std::string& node_name, const std::string& value) const override;
Status
CreateTable(const TableSchema& param) override;
CreateCollection(const CollectionParam& param) override;
bool
HasTable(const std::string& table_name) override;
HasCollection(const std::string& collection_name) override;
Status
DropTable(const std::string& table_name) override;
DropCollection(const std::string& collection_name) override;
Status
CreateIndex(const IndexParam& index_param) override;
Status
Insert(const std::string& table_name, const std::string& partition_tag, const std::vector<RowRecord>& record_array,
Insert(const std::string& collection_name,
const std::string& partition_tag,
const std::vector<Entity>& entity_array,
std::vector<int64_t>& id_array) override;
Status
GetVectorByID(const std::string& table_name, int64_t vector_id, RowRecord& vector_data) override;
GetEntityByID(const std::string& collection_name, int64_t entity_id, Entity& entity_data) override;
Status
GetIDsInSegment(const std::string& table_name, const std::string& segment_name,
GetIDsInSegment(const std::string& collection_name, const std::string& segment_name,
std::vector<int64_t>& id_array) override;
Status
Search(const std::string& table_name, const std::vector<std::string>& partition_tag_array,
const std::vector<RowRecord>& query_record_array, int64_t topk,
Search(const std::string& collection_name, const std::vector<std::string>& partition_tag_array,
const std::vector<Entity>& entity_array, int64_t topk,
const std::string& extra_params, TopKQueryResult& topk_query_result) override;
Status
DescribeTable(const std::string& table_name, TableSchema& table_schema) override;
DescribeCollection(const std::string& collection_name, CollectionParam& collection_schema) override;
Status
CountTable(const std::string& table_name, int64_t& row_count) override;
CountCollection(const std::string& collection_name, int64_t& entity_count) override;
Status
ShowTables(std::vector<std::string>& table_array) override;
ShowCollections(std::vector<std::string>& collection_array) override;
Status
ShowTableInfo(const std::string& table_name, TableInfo& table_info) override;
std::string
ClientVersion() const override;
std::string
ServerVersion() const override;
std::string
ServerStatus() const override;
Status
DeleteByID(const std::string& table_name, const std::vector<int64_t>& id_array) override;
ShowCollectionInfo(const std::string& collection_name, CollectionInfo& collection_info) override;
Status
PreloadTable(const std::string& table_name) const override;
DeleteByID(const std::string& collection_name, const std::vector<int64_t>& id_array) override;
Status
DescribeIndex(const std::string& table_name, IndexParam& index_param) const override;
PreloadCollection(const std::string& collection_name) const override;
Status
DropIndex(const std::string& table_name) const override;
DescribeIndex(const std::string& collection_name, IndexParam& index_param) const override;
Status
CreatePartition(const PartitionParam& param) override;
DropIndex(const std::string& collection_name) const override;
Status
ShowPartitions(const std::string& table_name, PartitionTagList& partition_tag_array) const override;
CreatePartition(const PartitionParam& partition_param) override;
Status
DropPartition(const PartitionParam& param) override;
ShowPartitions(const std::string& collection_name, PartitionTagList& partition_tag_array) const override;
Status
GetConfig(const std::string& node_name, std::string& value) const override;
Status
SetConfig(const std::string& node_name, const std::string& value) const override;
DropPartition(const PartitionParam& partition_param) override;
Status
FlushTable(const std::string& table_name) override;
FlushCollection(const std::string& collection_name) override;
Status
Flush() override;
Status
CompactTable(const std::string& table_name) override;
CompactCollection(const std::string& collection_name) override;
private:
std::shared_ptr<ClientProxy> client_proxy_;
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册