#1702 Optimize request handler to combine similar query (#1727)

* #1686 API search_in_files cannot work correctly when vectors is stored in certain non-default partition

Signed-off-by: yhmo <yihua.mo@zilliz.com>

* #1686 API search_in_files cannot work correctly when vectors is stored in certain non-default partition

Signed-off-by: groot <yihua.mo@zilliz.com>

* refine request code

Signed-off-by: groot <yihua.mo@zilliz.com>

* typo

Signed-off-by: groot <yihua.mo@zilliz.com>

* combine search request

Signed-off-by: groot <yihua.mo@zilliz.com>

* combine search request

Signed-off-by: groot <yihua.mo@zilliz.com>

* #1728 Optimize request handler to combine similar query

Signed-off-by: groot <yihua.mo@zilliz.com>

* typo

Signed-off-by: groot <yihua.mo@zilliz.com>

* remove some log
pull/1725/head^2
groot 2020-03-23 18:26:18 +08:00 committed by GitHub
parent 4fa45dc754
commit 99470b4dfa
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
64 changed files with 1134 additions and 259 deletions

View File

@ -74,10 +74,12 @@ set(thirdparty_files
aux_source_directory(${MILVUS_ENGINE_SRC}/server server_service_files)
aux_source_directory(${MILVUS_ENGINE_SRC}/server/delivery/request delivery_request_files)
aux_source_directory(${MILVUS_ENGINE_SRC}/server/delivery/strategy delivery_strategy_files)
aux_source_directory(${MILVUS_ENGINE_SRC}/server/delivery delivery_files)
set(server_files
${server_service_files}
${delivery_request_files}
${delivery_strategy_files}
${delivery_files}
)

View File

@ -0,0 +1,77 @@
// Copyright (C) 2019-2020 Zilliz. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance
// with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software distributed under the License
// is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
// or implied. See the License for the specific language governing permissions and limitations under the License.
#include "server/delivery/RequestQueue.h"
#include "server/delivery/strategy/RequestStrategy.h"
#include "server/delivery/strategy/SearchReqStrategy.h"
#include "utils/Log.h"
#include <fiu-local.h>
#include <unistd.h>
#include <queue>
#include <utility>
namespace milvus {
namespace server {
namespace {
Status
ScheduleRequest(const BaseRequestPtr& request, std::queue<BaseRequestPtr>& queue) {
#if 1
if (request == nullptr) {
return Status(SERVER_NULL_POINTER, "request schedule cannot handle null object");
}
if (queue.empty()) {
queue.push(request);
return Status::OK();
}
static std::map<BaseRequest::RequestType, RequestStrategyPtr> s_schedulers = {
{BaseRequest::kSearch, std::make_shared<SearchReqStrategy>()}};
auto iter = s_schedulers.find(request->GetRequestType());
if (iter == s_schedulers.end() || iter->second == nullptr) {
queue.push(request);
} else {
iter->second->ReScheduleQueue(request, queue);
}
#else
queue.push(request);
#endif
return Status::OK();
}
} // namespace
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
RequestQueue::RequestQueue() {
}
RequestQueue::~RequestQueue() {
}
BaseRequestPtr
RequestQueue::TakeRequest() {
return Take();
}
Status
RequestQueue::PutRequest(const BaseRequestPtr& request_ptr) {
std::unique_lock<std::mutex> lock(mtx);
full_.wait(lock, [this] { return (queue_.size() < capacity_); });
auto status = ScheduleRequest(request_ptr, queue_);
empty_.notify_all();
return status;
}
} // namespace server
} // namespace milvus

View File

@ -0,0 +1,44 @@
// Copyright (C) 2019-2020 Zilliz. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance
// with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software distributed under the License
// is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
// or implied. See the License for the specific language governing permissions and limitations under the License.
#pragma once
#include "server/delivery/request/BaseRequest.h"
#include "utils/BlockingQueue.h"
#include "utils/Status.h"
#include <map>
#include <memory>
#include <string>
#include <thread>
#include <vector>
namespace milvus {
namespace server {
using BlockingRequestQueue = BlockingQueue<BaseRequestPtr>;
class RequestQueue : public BlockingRequestQueue {
public:
RequestQueue();
virtual ~RequestQueue();
BaseRequestPtr
TakeRequest();
Status
PutRequest(const BaseRequestPtr& request_ptr);
};
using RequestQueuePtr = std::shared_ptr<RequestQueue>;
} // namespace server
} // namespace milvus

View File

@ -105,7 +105,7 @@ RequestScheduler::TakeToExecute(RequestQueuePtr request_queue) {
}
while (true) {
BaseRequestPtr request = request_queue->Take();
BaseRequestPtr request = request_queue->TakeRequest();
if (request == nullptr) {
SERVER_LOG_ERROR << "Take null from request queue, stop thread";
break; // stop the thread
@ -131,10 +131,10 @@ RequestScheduler::PutToQueue(const BaseRequestPtr& request_ptr) {
std::string group_name = request_ptr->RequestGroup();
if (request_groups_.count(group_name) > 0) {
request_groups_[group_name]->Put(request_ptr);
request_groups_[group_name]->PutRequest(request_ptr);
} else {
RequestQueuePtr queue = std::make_shared<RequestQueue>();
queue->Put(request_ptr);
queue->PutRequest(request_ptr);
request_groups_.insert(std::make_pair(group_name, queue));
fiu_do_on("RequestScheduler.PutToQueue.null_queue", queue = nullptr);

View File

@ -11,8 +11,7 @@
#pragma once
#include "server/delivery/request/BaseRequest.h"
#include "utils/BlockingQueue.h"
#include "server/delivery/RequestQueue.h"
#include "utils/Status.h"
#include <map>
@ -24,8 +23,6 @@
namespace milvus {
namespace server {
using RequestQueue = BlockingQueue<BaseRequestPtr>;
using RequestQueuePtr = std::shared_ptr<RequestQueue>;
using ThreadPtr = std::shared_ptr<std::thread>;
class RequestScheduler {

View File

@ -11,13 +11,72 @@
#include "server/delivery/request/BaseRequest.h"
#include "utils/CommonUtil.h"
#include "utils/Exception.h"
#include "utils/Log.h"
#include <map>
namespace milvus {
namespace server {
BaseRequest::BaseRequest(const std::shared_ptr<Context>& context, const std::string& request_group, bool async)
: context_(context), request_group_(request_group), async_(async), done_(false) {
static const char* DQL_REQUEST_GROUP = "dql";
static const char* DDL_DML_REQUEST_GROUP = "ddl_dml";
static const char* INFO_REQUEST_GROUP = "info";
namespace {
std::string
RequestGroup(BaseRequest::RequestType type) {
static std::map<BaseRequest::RequestType, std::string> s_map_type_group = {
// general operations
{BaseRequest::kCmd, INFO_REQUEST_GROUP},
// data operations
{BaseRequest::kInsert, DDL_DML_REQUEST_GROUP},
{BaseRequest::kCompact, DDL_DML_REQUEST_GROUP},
{BaseRequest::kFlush, DDL_DML_REQUEST_GROUP},
{BaseRequest::kDeleteByID, DDL_DML_REQUEST_GROUP},
{BaseRequest::kGetVectorByID, INFO_REQUEST_GROUP},
{BaseRequest::kGetVectorIDs, INFO_REQUEST_GROUP},
// table operations
{BaseRequest::kShowTables, INFO_REQUEST_GROUP},
{BaseRequest::kCreateTable, DDL_DML_REQUEST_GROUP},
{BaseRequest::kHasTable, INFO_REQUEST_GROUP},
{BaseRequest::kDescribeTable, INFO_REQUEST_GROUP},
{BaseRequest::kCountTable, INFO_REQUEST_GROUP},
{BaseRequest::kShowTableInfo, INFO_REQUEST_GROUP},
{BaseRequest::kDropTable, DDL_DML_REQUEST_GROUP},
{BaseRequest::kPreloadTable, DQL_REQUEST_GROUP},
// partition operations
{BaseRequest::kCreatePartition, DDL_DML_REQUEST_GROUP},
{BaseRequest::kShowPartitions, INFO_REQUEST_GROUP},
{BaseRequest::kDropPartition, DDL_DML_REQUEST_GROUP},
// index operations
{BaseRequest::kCreateIndex, DDL_DML_REQUEST_GROUP},
{BaseRequest::kDescribeIndex, INFO_REQUEST_GROUP},
{BaseRequest::kDropIndex, DDL_DML_REQUEST_GROUP},
// search operations
{BaseRequest::kSearchByID, DQL_REQUEST_GROUP},
{BaseRequest::kSearch, DQL_REQUEST_GROUP},
{BaseRequest::kSearchCombine, DQL_REQUEST_GROUP},
};
auto iter = s_map_type_group.find(type);
if (iter == s_map_type_group.end()) {
SERVER_LOG_ERROR << "Unsupported request type: " << type;
throw Exception(SERVER_NOT_IMPLEMENT, "request group undefined");
}
return iter->second;
}
} // namespace
BaseRequest::BaseRequest(const std::shared_ptr<milvus::server::Context>& context, BaseRequest::RequestType type,
bool async)
: context_(context), type_(type), async_(async), done_(false) {
request_group_ = milvus::server::RequestGroup(type);
}
BaseRequest::~BaseRequest() {
@ -37,11 +96,12 @@ BaseRequest::Done() {
finish_cond_.notify_all();
}
Status
BaseRequest::SetStatus(ErrorCode error_code, const std::string& error_msg) {
status_ = Status(error_code, error_msg);
SERVER_LOG_ERROR << error_msg;
return status_;
void
BaseRequest::set_status(const Status& status) {
status_ = status;
if (!status_.ok()) {
SERVER_LOG_ERROR << status_.message();
}
}
std::string
@ -55,7 +115,6 @@ Status
BaseRequest::WaitToFinish() {
std::unique_lock<std::mutex> lock(finish_mtx_);
finish_cond_.wait(lock, [this] { return done_; });
return status_;
}

View File

@ -31,10 +31,6 @@
namespace milvus {
namespace server {
static const char* DQL_REQUEST_GROUP = "dql";
static const char* DDL_DML_REQUEST_GROUP = "ddl_dml";
static const char* INFO_REQUEST_GROUP = "info";
struct TableSchema {
std::string table_name_;
int64_t dimension_;
@ -117,8 +113,47 @@ struct TableInfo {
};
class BaseRequest {
public:
enum RequestType {
// general operations
kCmd = 100,
// data operations
kInsert = 200,
kCompact,
kFlush,
kDeleteByID,
kGetVectorByID,
kGetVectorIDs,
// table operations
kShowTables = 300,
kCreateTable,
kHasTable,
kDescribeTable,
kCountTable,
kShowTableInfo,
kDropTable,
kPreloadTable,
// partition operations
kCreatePartition = 400,
kShowPartitions,
kDropPartition,
// index operations
kCreateIndex = 500,
kDescribeIndex,
kDropIndex,
// search operations
kSearchByID = 600,
kSearch,
kSearchCombine,
};
protected:
BaseRequest(const std::shared_ptr<Context>& context, const std::string& request_group, bool async = false);
BaseRequest(const std::shared_ptr<Context>& context, BaseRequest::RequestType type, bool async = false);
virtual ~BaseRequest();
@ -132,6 +167,11 @@ class BaseRequest {
Status
WaitToFinish();
RequestType
GetRequestType() const {
return type_;
}
std::string
RequestGroup() const {
return request_group_;
@ -142,6 +182,9 @@ class BaseRequest {
return status_;
}
void
set_status(const Status& status);
bool
IsAsync() const {
return async_;
@ -151,22 +194,26 @@ class BaseRequest {
virtual Status
OnExecute() = 0;
Status
SetStatus(ErrorCode error_code, const std::string& error_msg);
std::string
TableNotExistMsg(const std::string& table_name);
protected:
const std::shared_ptr<Context>& context_;
const std::shared_ptr<milvus::server::Context>& context_;
mutable std::mutex finish_mtx_;
std::condition_variable finish_cond_;
RequestType type_;
std::string request_group_;
bool async_;
bool done_;
Status status_;
public:
const std::shared_ptr<milvus::server::Context>&
Context() const {
return context_;
}
};
using BaseRequestPtr = std::shared_ptr<BaseRequest>;

View File

@ -21,12 +21,14 @@
namespace milvus {
namespace server {
CmdRequest::CmdRequest(const std::shared_ptr<Context>& context, const std::string& cmd, std::string& result)
: BaseRequest(context, INFO_REQUEST_GROUP), cmd_(cmd), result_(result) {
CmdRequest::CmdRequest(const std::shared_ptr<milvus::server::Context>& context, const std::string& cmd,
std::string& result)
: BaseRequest(context, BaseRequest::kCmd), cmd_(cmd), result_(result) {
}
BaseRequestPtr
CmdRequest::Create(const std::shared_ptr<Context>& context, const std::string& cmd, std::string& result) {
CmdRequest::Create(const std::shared_ptr<milvus::server::Context>& context, const std::string& cmd,
std::string& result) {
return std::shared_ptr<BaseRequest>(new CmdRequest(context, cmd, result));
}

View File

@ -22,10 +22,10 @@ namespace server {
class CmdRequest : public BaseRequest {
public:
static BaseRequestPtr
Create(const std::shared_ptr<Context>& context, const std::string& cmd, std::string& result);
Create(const std::shared_ptr<milvus::server::Context>& context, const std::string& cmd, std::string& result);
protected:
CmdRequest(const std::shared_ptr<Context>& context, const std::string& cmd, std::string& result);
CmdRequest(const std::shared_ptr<milvus::server::Context>& context, const std::string& cmd, std::string& result);
Status
OnExecute() override;

View File

@ -26,12 +26,12 @@
namespace milvus {
namespace server {
CompactRequest::CompactRequest(const std::shared_ptr<Context>& context, const std::string& table_name)
: BaseRequest(context, DDL_DML_REQUEST_GROUP), table_name_(table_name) {
CompactRequest::CompactRequest(const std::shared_ptr<milvus::server::Context>& context, const std::string& table_name)
: BaseRequest(context, BaseRequest::kCompact), table_name_(table_name) {
}
BaseRequestPtr
CompactRequest::Create(const std::shared_ptr<Context>& context, const std::string& table_name) {
CompactRequest::Create(const std::shared_ptr<milvus::server::Context>& context, const std::string& table_name) {
return std::shared_ptr<BaseRequest>(new CompactRequest(context, table_name));
}

View File

@ -28,10 +28,10 @@ namespace server {
class CompactRequest : public BaseRequest {
public:
static BaseRequestPtr
Create(const std::shared_ptr<Context>& context, const std::string& table_name);
Create(const std::shared_ptr<milvus::server::Context>& context, const std::string& table_name);
protected:
CompactRequest(const std::shared_ptr<Context>& context, const std::string& table_name);
CompactRequest(const std::shared_ptr<milvus::server::Context>& context, const std::string& table_name);
Status
OnExecute() override;

View File

@ -22,13 +22,14 @@
namespace milvus {
namespace server {
CountTableRequest::CountTableRequest(const std::shared_ptr<Context>& context, const std::string& table_name,
int64_t& row_count)
: BaseRequest(context, INFO_REQUEST_GROUP), table_name_(table_name), row_count_(row_count) {
CountTableRequest::CountTableRequest(const std::shared_ptr<milvus::server::Context>& context,
const std::string& table_name, int64_t& row_count)
: BaseRequest(context, BaseRequest::kCountTable), table_name_(table_name), row_count_(row_count) {
}
BaseRequestPtr
CountTableRequest::Create(const std::shared_ptr<Context>& context, const std::string& table_name, int64_t& row_count) {
CountTableRequest::Create(const std::shared_ptr<milvus::server::Context>& context, const std::string& table_name,
int64_t& row_count) {
return std::shared_ptr<BaseRequest>(new CountTableRequest(context, table_name, row_count));
}

View File

@ -22,10 +22,11 @@ namespace server {
class CountTableRequest : public BaseRequest {
public:
static BaseRequestPtr
Create(const std::shared_ptr<Context>& context, const std::string& table_name, int64_t& row_count);
Create(const std::shared_ptr<milvus::server::Context>& context, const std::string& table_name, int64_t& row_count);
protected:
CountTableRequest(const std::shared_ptr<Context>& context, const std::string& table_name, int64_t& row_count);
CountTableRequest(const std::shared_ptr<milvus::server::Context>& context, const std::string& table_name,
int64_t& row_count);
Status
OnExecute() override;

View File

@ -24,17 +24,18 @@
namespace milvus {
namespace server {
CreateIndexRequest::CreateIndexRequest(const std::shared_ptr<Context>& context, const std::string& table_name,
int64_t index_type, const milvus::json& json_params)
: BaseRequest(context, DDL_DML_REQUEST_GROUP),
CreateIndexRequest::CreateIndexRequest(const std::shared_ptr<milvus::server::Context>& context,
const std::string& table_name, int64_t index_type,
const milvus::json& json_params)
: BaseRequest(context, BaseRequest::kCreateIndex),
table_name_(table_name),
index_type_(index_type),
json_params_(json_params) {
}
BaseRequestPtr
CreateIndexRequest::Create(const std::shared_ptr<Context>& context, const std::string& table_name, int64_t index_type,
const milvus::json& json_params) {
CreateIndexRequest::Create(const std::shared_ptr<milvus::server::Context>& context, const std::string& table_name,
int64_t index_type, const milvus::json& json_params) {
return std::shared_ptr<BaseRequest>(new CreateIndexRequest(context, table_name, index_type, json_params));
}

View File

@ -21,12 +21,12 @@ namespace server {
class CreateIndexRequest : public BaseRequest {
public:
static BaseRequestPtr
Create(const std::shared_ptr<Context>& context, const std::string& table_name, int64_t index_type,
Create(const std::shared_ptr<milvus::server::Context>& context, const std::string& table_name, int64_t index_type,
const milvus::json& json_params);
protected:
CreateIndexRequest(const std::shared_ptr<Context>& context, const std::string& table_name, int64_t index_type,
const milvus::json& json_params);
CreateIndexRequest(const std::shared_ptr<milvus::server::Context>& context, const std::string& table_name,
int64_t index_type, const milvus::json& json_params);
Status
OnExecute() override;

View File

@ -22,13 +22,13 @@
namespace milvus {
namespace server {
CreatePartitionRequest::CreatePartitionRequest(const std::shared_ptr<Context>& context, const std::string& table_name,
const std::string& tag)
: BaseRequest(context, DDL_DML_REQUEST_GROUP), table_name_(table_name), tag_(tag) {
CreatePartitionRequest::CreatePartitionRequest(const std::shared_ptr<milvus::server::Context>& context,
const std::string& table_name, const std::string& tag)
: BaseRequest(context, BaseRequest::kCreatePartition), table_name_(table_name), tag_(tag) {
}
BaseRequestPtr
CreatePartitionRequest::Create(const std::shared_ptr<Context>& context, const std::string& table_name,
CreatePartitionRequest::Create(const std::shared_ptr<milvus::server::Context>& context, const std::string& table_name,
const std::string& tag) {
return std::shared_ptr<BaseRequest>(new CreatePartitionRequest(context, table_name, tag));
}

View File

@ -21,10 +21,11 @@ namespace server {
class CreatePartitionRequest : public BaseRequest {
public:
static BaseRequestPtr
Create(const std::shared_ptr<Context>& context, const std::string& partition_name, const std::string& tag);
Create(const std::shared_ptr<milvus::server::Context>& context, const std::string& partition_name,
const std::string& tag);
protected:
CreatePartitionRequest(const std::shared_ptr<Context>& context, const std::string& table_name,
CreatePartitionRequest(const std::shared_ptr<milvus::server::Context>& context, const std::string& table_name,
const std::string& tag);
Status

View File

@ -24,9 +24,10 @@
namespace milvus {
namespace server {
CreateTableRequest::CreateTableRequest(const std::shared_ptr<Context>& context, const std::string& table_name,
int64_t dimension, int64_t index_file_size, int64_t metric_type)
: BaseRequest(context, DDL_DML_REQUEST_GROUP),
CreateTableRequest::CreateTableRequest(const std::shared_ptr<milvus::server::Context>& context,
const std::string& table_name, int64_t dimension, int64_t index_file_size,
int64_t metric_type)
: BaseRequest(context, BaseRequest::kCreateTable),
table_name_(table_name),
dimension_(dimension),
index_file_size_(index_file_size),
@ -34,8 +35,8 @@ CreateTableRequest::CreateTableRequest(const std::shared_ptr<Context>& context,
}
BaseRequestPtr
CreateTableRequest::Create(const std::shared_ptr<Context>& context, const std::string& table_name, int64_t dimension,
int64_t index_file_size, int64_t metric_type) {
CreateTableRequest::Create(const std::shared_ptr<milvus::server::Context>& context, const std::string& table_name,
int64_t dimension, int64_t index_file_size, int64_t metric_type) {
return std::shared_ptr<BaseRequest>(
new CreateTableRequest(context, table_name, dimension, index_file_size, metric_type));
}

View File

@ -22,12 +22,12 @@ namespace server {
class CreateTableRequest : public BaseRequest {
public:
static BaseRequestPtr
Create(const std::shared_ptr<Context>& context, const std::string& table_name, int64_t dimension,
Create(const std::shared_ptr<milvus::server::Context>& context, const std::string& table_name, int64_t dimension,
int64_t index_file_size, int64_t metric_type);
protected:
CreateTableRequest(const std::shared_ptr<Context>& context, const std::string& table_name, int64_t dimension,
int64_t index_file_size, int64_t metric_type);
CreateTableRequest(const std::shared_ptr<milvus::server::Context>& context, const std::string& table_name,
int64_t dimension, int64_t index_file_size, int64_t metric_type);
Status
OnExecute() override;

View File

@ -29,13 +29,13 @@
namespace milvus {
namespace server {
DeleteByIDRequest::DeleteByIDRequest(const std::shared_ptr<Context>& context, const std::string& table_name,
const std::vector<int64_t>& vector_ids)
: BaseRequest(context, DDL_DML_REQUEST_GROUP), table_name_(table_name), vector_ids_(vector_ids) {
DeleteByIDRequest::DeleteByIDRequest(const std::shared_ptr<milvus::server::Context>& context,
const std::string& table_name, const std::vector<int64_t>& vector_ids)
: BaseRequest(context, BaseRequest::kDeleteByID), table_name_(table_name), vector_ids_(vector_ids) {
}
BaseRequestPtr
DeleteByIDRequest::Create(const std::shared_ptr<Context>& context, const std::string& table_name,
DeleteByIDRequest::Create(const std::shared_ptr<milvus::server::Context>& context, const std::string& table_name,
const std::vector<int64_t>& vector_ids) {
return std::shared_ptr<BaseRequest>(new DeleteByIDRequest(context, table_name, vector_ids));
}

View File

@ -29,11 +29,11 @@ namespace server {
class DeleteByIDRequest : public BaseRequest {
public:
static BaseRequestPtr
Create(const std::shared_ptr<Context>& context, const std::string& table_name,
Create(const std::shared_ptr<milvus::server::Context>& context, const std::string& table_name,
const std::vector<int64_t>& vector_ids);
protected:
DeleteByIDRequest(const std::shared_ptr<Context>& context, const std::string& table_name,
DeleteByIDRequest(const std::shared_ptr<milvus::server::Context>& context, const std::string& table_name,
const std::vector<int64_t>& vector_ids);
Status

View File

@ -21,13 +21,13 @@
namespace milvus {
namespace server {
DescribeIndexRequest::DescribeIndexRequest(const std::shared_ptr<Context>& context, const std::string& table_name,
IndexParam& index_param)
: BaseRequest(context, INFO_REQUEST_GROUP), table_name_(table_name), index_param_(index_param) {
DescribeIndexRequest::DescribeIndexRequest(const std::shared_ptr<milvus::server::Context>& context,
const std::string& table_name, IndexParam& index_param)
: BaseRequest(context, BaseRequest::kDescribeIndex), table_name_(table_name), index_param_(index_param) {
}
BaseRequestPtr
DescribeIndexRequest::Create(const std::shared_ptr<Context>& context, const std::string& table_name,
DescribeIndexRequest::Create(const std::shared_ptr<milvus::server::Context>& context, const std::string& table_name,
IndexParam& index_param) {
return std::shared_ptr<BaseRequest>(new DescribeIndexRequest(context, table_name, index_param));
}

View File

@ -22,10 +22,11 @@ namespace server {
class DescribeIndexRequest : public BaseRequest {
public:
static BaseRequestPtr
Create(const std::shared_ptr<Context>& context, const std::string& table_name, IndexParam& index_param);
Create(const std::shared_ptr<milvus::server::Context>& context, const std::string& table_name,
IndexParam& index_param);
protected:
DescribeIndexRequest(const std::shared_ptr<Context>& context, const std::string& table_name,
DescribeIndexRequest(const std::shared_ptr<milvus::server::Context>& context, const std::string& table_name,
IndexParam& index_param);
Status

View File

@ -21,13 +21,13 @@
namespace milvus {
namespace server {
DescribeTableRequest::DescribeTableRequest(const std::shared_ptr<Context>& context, const std::string& table_name,
TableSchema& schema)
: BaseRequest(context, INFO_REQUEST_GROUP), table_name_(table_name), schema_(schema) {
DescribeTableRequest::DescribeTableRequest(const std::shared_ptr<milvus::server::Context>& context,
const std::string& table_name, TableSchema& schema)
: BaseRequest(context, BaseRequest::kDescribeTable), table_name_(table_name), schema_(schema) {
}
BaseRequestPtr
DescribeTableRequest::Create(const std::shared_ptr<Context>& context, const std::string& table_name,
DescribeTableRequest::Create(const std::shared_ptr<milvus::server::Context>& context, const std::string& table_name,
TableSchema& schema) {
return std::shared_ptr<BaseRequest>(new DescribeTableRequest(context, table_name, schema));
}

View File

@ -22,10 +22,11 @@ namespace server {
class DescribeTableRequest : public BaseRequest {
public:
static BaseRequestPtr
Create(const std::shared_ptr<Context>& context, const std::string& table_name, TableSchema& schema);
Create(const std::shared_ptr<milvus::server::Context>& context, const std::string& table_name, TableSchema& schema);
protected:
DescribeTableRequest(const std::shared_ptr<Context>& context, const std::string& table_name, TableSchema& schema);
DescribeTableRequest(const std::shared_ptr<milvus::server::Context>& context, const std::string& table_name,
TableSchema& schema);
Status
OnExecute() override;

View File

@ -21,12 +21,13 @@
namespace milvus {
namespace server {
DropIndexRequest::DropIndexRequest(const std::shared_ptr<Context>& context, const std::string& table_name)
: BaseRequest(context, DDL_DML_REQUEST_GROUP), table_name_(table_name) {
DropIndexRequest::DropIndexRequest(const std::shared_ptr<milvus::server::Context>& context,
const std::string& table_name)
: BaseRequest(context, BaseRequest::kDropIndex), table_name_(table_name) {
}
BaseRequestPtr
DropIndexRequest::Create(const std::shared_ptr<Context>& context, const std::string& table_name) {
DropIndexRequest::Create(const std::shared_ptr<milvus::server::Context>& context, const std::string& table_name) {
return std::shared_ptr<BaseRequest>(new DropIndexRequest(context, table_name));
}

View File

@ -22,10 +22,10 @@ namespace server {
class DropIndexRequest : public BaseRequest {
public:
static BaseRequestPtr
Create(const std::shared_ptr<Context>& context, const std::string& table_name);
Create(const std::shared_ptr<milvus::server::Context>& context, const std::string& table_name);
protected:
DropIndexRequest(const std::shared_ptr<Context>& context, const std::string& table_name);
DropIndexRequest(const std::shared_ptr<milvus::server::Context>& context, const std::string& table_name);
Status
OnExecute() override;

View File

@ -22,13 +22,13 @@
namespace milvus {
namespace server {
DropPartitionRequest::DropPartitionRequest(const std::shared_ptr<Context>& context, const std::string& table_name,
const std::string& tag)
: BaseRequest(context, DDL_DML_REQUEST_GROUP), table_name_(table_name), tag_(tag) {
DropPartitionRequest::DropPartitionRequest(const std::shared_ptr<milvus::server::Context>& context,
const std::string& table_name, const std::string& tag)
: BaseRequest(context, BaseRequest::kDropPartition), table_name_(table_name), tag_(tag) {
}
BaseRequestPtr
DropPartitionRequest::Create(const std::shared_ptr<Context>& context, const std::string& table_name,
DropPartitionRequest::Create(const std::shared_ptr<milvus::server::Context>& context, const std::string& table_name,
const std::string& tag) {
return std::shared_ptr<BaseRequest>(new DropPartitionRequest(context, table_name, tag));
}

View File

@ -21,10 +21,11 @@ namespace server {
class DropPartitionRequest : public BaseRequest {
public:
static BaseRequestPtr
Create(const std::shared_ptr<Context>& context, const std::string& table_name, const std::string& tag);
Create(const std::shared_ptr<milvus::server::Context>& context, const std::string& table_name,
const std::string& tag);
protected:
DropPartitionRequest(const std::shared_ptr<Context>& context, const std::string& table_name,
DropPartitionRequest(const std::shared_ptr<milvus::server::Context>& context, const std::string& table_name,
const std::string& tag);
Status

View File

@ -22,12 +22,13 @@
namespace milvus {
namespace server {
DropTableRequest::DropTableRequest(const std::shared_ptr<Context>& context, const std::string& table_name)
: BaseRequest(context, DDL_DML_REQUEST_GROUP), table_name_(table_name) {
DropTableRequest::DropTableRequest(const std::shared_ptr<milvus::server::Context>& context,
const std::string& table_name)
: BaseRequest(context, BaseRequest::kDropTable), table_name_(table_name) {
}
BaseRequestPtr
DropTableRequest::Create(const std::shared_ptr<Context>& context, const std::string& table_name) {
DropTableRequest::Create(const std::shared_ptr<milvus::server::Context>& context, const std::string& table_name) {
return std::shared_ptr<BaseRequest>(new DropTableRequest(context, table_name));
}

View File

@ -22,10 +22,10 @@ namespace server {
class DropTableRequest : public BaseRequest {
public:
static BaseRequestPtr
Create(const std::shared_ptr<Context>& context, const std::string& table_name);
Create(const std::shared_ptr<milvus::server::Context>& context, const std::string& table_name);
protected:
DropTableRequest(const std::shared_ptr<Context>& context, const std::string& table_name);
DropTableRequest(const std::shared_ptr<milvus::server::Context>& context, const std::string& table_name);
Status
OnExecute() override;

View File

@ -26,12 +26,14 @@
namespace milvus {
namespace server {
FlushRequest::FlushRequest(const std::shared_ptr<Context>& context, const std::vector<std::string>& table_names)
: BaseRequest(context, DDL_DML_REQUEST_GROUP), table_names_(table_names) {
FlushRequest::FlushRequest(const std::shared_ptr<milvus::server::Context>& context,
const std::vector<std::string>& table_names)
: BaseRequest(context, BaseRequest::kFlush), table_names_(table_names) {
}
BaseRequestPtr
FlushRequest::Create(const std::shared_ptr<Context>& context, const std::vector<std::string>& table_names) {
FlushRequest::Create(const std::shared_ptr<milvus::server::Context>& context,
const std::vector<std::string>& table_names) {
return std::shared_ptr<BaseRequest>(new FlushRequest(context, table_names));
}

View File

@ -29,10 +29,10 @@ namespace server {
class FlushRequest : public BaseRequest {
public:
static BaseRequestPtr
Create(const std::shared_ptr<Context>& context, const std::vector<std::string>& table_names);
Create(const std::shared_ptr<milvus::server::Context>& context, const std::vector<std::string>& table_names);
protected:
FlushRequest(const std::shared_ptr<Context>& context, const std::vector<std::string>& table_names);
FlushRequest(const std::shared_ptr<milvus::server::Context>& context, const std::vector<std::string>& table_names);
Status
OnExecute() override;

View File

@ -27,13 +27,14 @@
namespace milvus {
namespace server {
GetVectorByIDRequest::GetVectorByIDRequest(const std::shared_ptr<Context>& context, const std::string& table_name,
const std::vector<int64_t>& ids, engine::VectorsData& vectors)
: BaseRequest(context, INFO_REQUEST_GROUP), table_name_(table_name), ids_(ids), vectors_(vectors) {
GetVectorByIDRequest::GetVectorByIDRequest(const std::shared_ptr<milvus::server::Context>& context,
const std::string& table_name, const std::vector<int64_t>& ids,
engine::VectorsData& vectors)
: BaseRequest(context, BaseRequest::kGetVectorByID), table_name_(table_name), ids_(ids), vectors_(vectors) {
}
BaseRequestPtr
GetVectorByIDRequest::Create(const std::shared_ptr<Context>& context, const std::string& table_name,
GetVectorByIDRequest::Create(const std::shared_ptr<milvus::server::Context>& context, const std::string& table_name,
const std::vector<int64_t>& ids, engine::VectorsData& vectors) {
return std::shared_ptr<BaseRequest>(new GetVectorByIDRequest(context, table_name, ids, vectors));
}

View File

@ -29,11 +29,11 @@ namespace server {
class GetVectorByIDRequest : public BaseRequest {
public:
static BaseRequestPtr
Create(const std::shared_ptr<Context>& context, const std::string& table_name, const std::vector<int64_t>& ids,
engine::VectorsData& vectors);
Create(const std::shared_ptr<milvus::server::Context>& context, const std::string& table_name,
const std::vector<int64_t>& ids, engine::VectorsData& vectors);
protected:
GetVectorByIDRequest(const std::shared_ptr<Context>& context, const std::string& table_name,
GetVectorByIDRequest(const std::shared_ptr<milvus::server::Context>& context, const std::string& table_name,
const std::vector<int64_t>& ids, engine::VectorsData& vectors);
Status

View File

@ -27,16 +27,17 @@
namespace milvus {
namespace server {
GetVectorIDsRequest::GetVectorIDsRequest(const std::shared_ptr<Context>& context, const std::string& table_name,
const std::string& segment_name, std::vector<int64_t>& vector_ids)
: BaseRequest(context, INFO_REQUEST_GROUP),
GetVectorIDsRequest::GetVectorIDsRequest(const std::shared_ptr<milvus::server::Context>& context,
const std::string& table_name, const std::string& segment_name,
std::vector<int64_t>& vector_ids)
: BaseRequest(context, BaseRequest::kGetVectorIDs),
table_name_(table_name),
segment_name_(segment_name),
vector_ids_(vector_ids) {
}
BaseRequestPtr
GetVectorIDsRequest::Create(const std::shared_ptr<Context>& context, const std::string& table_name,
GetVectorIDsRequest::Create(const std::shared_ptr<milvus::server::Context>& context, const std::string& table_name,
const std::string& segment_name, std::vector<int64_t>& vector_ids) {
return std::shared_ptr<BaseRequest>(new GetVectorIDsRequest(context, table_name, segment_name, vector_ids));
}

View File

@ -29,11 +29,11 @@ namespace server {
class GetVectorIDsRequest : public BaseRequest {
public:
static BaseRequestPtr
Create(const std::shared_ptr<Context>& context, const std::string& table_name, const std::string& segment_name,
std::vector<int64_t>& vector_ids);
Create(const std::shared_ptr<milvus::server::Context>& context, const std::string& table_name,
const std::string& segment_name, std::vector<int64_t>& vector_ids);
protected:
GetVectorIDsRequest(const std::shared_ptr<Context>& context, const std::string& table_name,
GetVectorIDsRequest(const std::shared_ptr<milvus::server::Context>& context, const std::string& table_name,
const std::string& segment_name, std::vector<int64_t>& vector_ids);
Status

View File

@ -21,13 +21,14 @@
namespace milvus {
namespace server {
HasTableRequest::HasTableRequest(const std::shared_ptr<Context>& context, const std::string& table_name,
HasTableRequest::HasTableRequest(const std::shared_ptr<milvus::server::Context>& context, const std::string& table_name,
bool& has_table)
: BaseRequest(context, INFO_REQUEST_GROUP), table_name_(table_name), has_table_(has_table) {
: BaseRequest(context, BaseRequest::kHasTable), table_name_(table_name), has_table_(has_table) {
}
BaseRequestPtr
HasTableRequest::Create(const std::shared_ptr<Context>& context, const std::string& table_name, bool& has_table) {
HasTableRequest::Create(const std::shared_ptr<milvus::server::Context>& context, const std::string& table_name,
bool& has_table) {
return std::shared_ptr<BaseRequest>(new HasTableRequest(context, table_name, has_table));
}

View File

@ -22,10 +22,11 @@ namespace server {
class HasTableRequest : public BaseRequest {
public:
static BaseRequestPtr
Create(const std::shared_ptr<Context>& context, const std::string& table_name, bool& has_table);
Create(const std::shared_ptr<milvus::server::Context>& context, const std::string& table_name, bool& has_table);
protected:
HasTableRequest(const std::shared_ptr<Context>& context, const std::string& table_name, bool& has_table);
HasTableRequest(const std::shared_ptr<milvus::server::Context>& context, const std::string& table_name,
bool& has_table);
Status
OnExecute() override;

View File

@ -28,16 +28,16 @@
namespace milvus {
namespace server {
InsertRequest::InsertRequest(const std::shared_ptr<Context>& context, const std::string& table_name,
InsertRequest::InsertRequest(const std::shared_ptr<milvus::server::Context>& context, const std::string& table_name,
engine::VectorsData& vectors, const std::string& partition_tag)
: BaseRequest(context, DDL_DML_REQUEST_GROUP),
: BaseRequest(context, BaseRequest::kInsert),
table_name_(table_name),
vectors_data_(vectors),
partition_tag_(partition_tag) {
}
BaseRequestPtr
InsertRequest::Create(const std::shared_ptr<Context>& context, const std::string& table_name,
InsertRequest::Create(const std::shared_ptr<milvus::server::Context>& context, const std::string& table_name,
engine::VectorsData& vectors, const std::string& partition_tag) {
return std::shared_ptr<BaseRequest>(new InsertRequest(context, table_name, vectors, partition_tag));
}

View File

@ -23,12 +23,12 @@ namespace server {
class InsertRequest : public BaseRequest {
public:
static BaseRequestPtr
Create(const std::shared_ptr<Context>& context, const std::string& table_name, engine::VectorsData& vectors,
const std::string& partition_tag);
Create(const std::shared_ptr<milvus::server::Context>& context, const std::string& table_name,
engine::VectorsData& vectors, const std::string& partition_tag);
protected:
InsertRequest(const std::shared_ptr<Context>& context, const std::string& table_name, engine::VectorsData& vectors,
const std::string& partition_tag);
InsertRequest(const std::shared_ptr<milvus::server::Context>& context, const std::string& table_name,
engine::VectorsData& vectors, const std::string& partition_tag);
Status
OnExecute() override;

View File

@ -21,12 +21,13 @@
namespace milvus {
namespace server {
PreloadTableRequest::PreloadTableRequest(const std::shared_ptr<Context>& context, const std::string& table_name)
: BaseRequest(context, DQL_REQUEST_GROUP), table_name_(table_name) {
PreloadTableRequest::PreloadTableRequest(const std::shared_ptr<milvus::server::Context>& context,
const std::string& table_name)
: BaseRequest(context, BaseRequest::kPreloadTable), table_name_(table_name) {
}
BaseRequestPtr
PreloadTableRequest::Create(const std::shared_ptr<Context>& context, const std::string& table_name) {
PreloadTableRequest::Create(const std::shared_ptr<milvus::server::Context>& context, const std::string& table_name) {
return std::shared_ptr<BaseRequest>(new PreloadTableRequest(context, table_name));
}

View File

@ -22,10 +22,10 @@ namespace server {
class PreloadTableRequest : public BaseRequest {
public:
static BaseRequestPtr
Create(const std::shared_ptr<Context>& context, const std::string& table_name);
Create(const std::shared_ptr<milvus::server::Context>& context, const std::string& table_name);
protected:
PreloadTableRequest(const std::shared_ptr<Context>& context, const std::string& table_name);
PreloadTableRequest(const std::shared_ptr<milvus::server::Context>& context, const std::string& table_name);
Status
OnExecute() override;

View File

@ -33,10 +33,11 @@
namespace milvus {
namespace server {
SearchByIDRequest::SearchByIDRequest(const std::shared_ptr<Context>& context, const std::string& table_name,
int64_t vector_id, int64_t topk, const milvus::json& extra_params,
const std::vector<std::string>& partition_list, TopKQueryResult& result)
: BaseRequest(context, DQL_REQUEST_GROUP),
SearchByIDRequest::SearchByIDRequest(const std::shared_ptr<milvus::server::Context>& context,
const std::string& table_name, int64_t vector_id, int64_t topk,
const milvus::json& extra_params, const std::vector<std::string>& partition_list,
TopKQueryResult& result)
: BaseRequest(context, BaseRequest::kSearchByID),
table_name_(table_name),
vector_id_(vector_id),
topk_(topk),
@ -46,8 +47,8 @@ SearchByIDRequest::SearchByIDRequest(const std::shared_ptr<Context>& context, co
}
BaseRequestPtr
SearchByIDRequest::Create(const std::shared_ptr<Context>& context, const std::string& table_name, int64_t vector_id,
int64_t topk, const milvus::json& extra_params,
SearchByIDRequest::Create(const std::shared_ptr<milvus::server::Context>& context, const std::string& table_name,
int64_t vector_id, int64_t topk, const milvus::json& extra_params,
const std::vector<std::string>& partition_list, TopKQueryResult& result) {
return std::shared_ptr<BaseRequest>(
new SearchByIDRequest(context, table_name, vector_id, topk, extra_params, partition_list, result));
@ -71,7 +72,13 @@ SearchByIDRequest::OnExecute() {
return status;
}
// step 3: check table existence
// step 3: check search topk
status = ValidationUtil::ValidateSearchTopk(topk_);
if (!status.ok()) {
return status;
}
// step 4: check table existence
// only process root table, ignore partition table
engine::meta::TableSchema table_schema;
table_schema.table_id_ = table_name_;
@ -88,12 +95,13 @@ SearchByIDRequest::OnExecute() {
}
}
// step 5: check search parameters
status = ValidationUtil::ValidateSearchParams(extra_params_, table_schema, topk_);
if (!status.ok()) {
return status;
}
// Check whether GPU search resource is enabled
// step 6: check whether GPU search resource is enabled
#ifdef MILVUS_GPU_VERSION
Config& config = Config::GetInstance();
bool gpu_enable;
@ -109,7 +117,7 @@ SearchByIDRequest::OnExecute() {
}
#endif
// Check table's index type supports search by id
// step 7: check table's index type supports search by id
if (table_schema.engine_type_ != (int32_t)engine::EngineType::FAISS_IDMAP &&
table_schema.engine_type_ != (int32_t)engine::EngineType::FAISS_BIN_IDMAP &&
table_schema.engine_type_ != (int32_t)engine::EngineType::FAISS_IVFFLAT &&
@ -121,15 +129,9 @@ SearchByIDRequest::OnExecute() {
return Status(SERVER_UNSUPPORTED_ERROR, err_msg);
}
// step 4: check search parameter
status = ValidationUtil::ValidateSearchTopk(topk_, table_schema);
if (!status.ok()) {
return status;
}
rc.RecordSection("check validation");
// step 5: search vectors
// step 8: search vectors
engine::ResultIds result_ids;
engine::ResultDistances result_distances;
@ -158,14 +160,13 @@ SearchByIDRequest::OnExecute() {
auto post_query_ctx = context_->Child("Constructing result");
// step 7: construct result array
// step 9: construct result array
result_.row_num_ = 1;
result_.distance_list_ = result_distances;
result_.id_list_ = result_ids;
post_query_ctx->GetTraceContext()->GetSpan()->Finish();
// step 8: print time cost percent
rc.RecordSection("construct result and send");
rc.ElapseFromBegin("totally cost");
} catch (std::exception& ex) {

View File

@ -29,13 +29,14 @@ namespace server {
class SearchByIDRequest : public BaseRequest {
public:
static BaseRequestPtr
Create(const std::shared_ptr<Context>& context, const std::string& table_name, int64_t vector_id, int64_t topk,
const milvus::json& extra_params, const std::vector<std::string>& partition_list, TopKQueryResult& result);
Create(const std::shared_ptr<milvus::server::Context>& context, const std::string& table_name, int64_t vector_id,
int64_t topk, const milvus::json& extra_params, const std::vector<std::string>& partition_list,
TopKQueryResult& result);
protected:
SearchByIDRequest(const std::shared_ptr<Context>& context, const std::string& table_name, int64_t vector_id,
int64_t topk, const milvus::json& extra_params, const std::vector<std::string>& partition_list,
TopKQueryResult& result);
SearchByIDRequest(const std::shared_ptr<milvus::server::Context>& context, const std::string& table_name,
int64_t vector_id, int64_t topk, const milvus::json& extra_params,
const std::vector<std::string>& partition_list, TopKQueryResult& result);
Status
OnExecute() override;

View File

@ -0,0 +1,363 @@
// Copyright (C) 2019-2020 Zilliz. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance
// with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software distributed under the License
// is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
// or implied. See the License for the specific language governing permissions and limitations under the License.
#include "server/delivery/request/SearchCombineRequest.h"
#include "db/Utils.h"
#include "server/DBWrapper.h"
#include "server/context/Context.h"
#include "utils/CommonUtil.h"
#include "utils/Log.h"
#include "utils/TimeRecorder.h"
#include "utils/ValidationUtil.h"
#include <memory>
#include <set>
namespace milvus {
namespace server {
namespace {
constexpr int64_t MAX_TOPK_GAP = 200;
void
GetUniqueList(const std::vector<std::string>& list, std::set<std::string>& unique_list) {
for (const std::string& item : list) {
unique_list.insert(item);
}
}
bool
IsSameList(const std::set<std::string>& left, const std::set<std::string>& right) {
if (left.size() != right.size()) {
return false;
}
std::set<std::string>::const_iterator iter_left;
std::set<std::string>::const_iterator iter_right;
for (iter_left = left.begin(), iter_right = right.begin(); iter_left != left.end(); iter_left++, iter_right++) {
if ((*iter_left) != (*iter_right)) {
return false;
}
}
return true;
}
void
FreeRequest(SearchRequestPtr& request, const Status& status) {
request->set_status(status);
request->Done();
}
} // namespace
SearchCombineRequest::SearchCombineRequest() : BaseRequest(nullptr, BaseRequest::kSearchCombine) {
}
Status
SearchCombineRequest::Combine(const SearchRequestPtr& request) {
if (request == nullptr) {
return Status(SERVER_NULL_POINTER, "");
}
// the request must be tested by CanCombine before invoke this function
// reset some parameters in necessary
if (request_list_.empty()) {
// validate first request input
auto status = ValidationUtil::ValidateTableName(request->TableName());
if (!status.ok()) {
return status;
}
status = ValidationUtil::ValidateSearchTopk(request->TopK());
if (!status.ok()) {
return status;
}
// assign base parameters
table_name_ = request->TableName();
min_topk_ = request->TopK() - MAX_TOPK_GAP / 2;
if (min_topk_ < 0) {
min_topk_ = 0;
}
max_topk_ = request->TopK() + MAX_TOPK_GAP / 2;
if (max_topk_ > QUERY_MAX_TOPK) {
max_topk_ = QUERY_MAX_TOPK;
}
extra_params_ = request->ExtraParams();
GetUniqueList(request->PartitionList(), partition_list_);
GetUniqueList(request->FileIDList(), file_id_list_);
}
request_list_.push_back(request);
return Status::OK();
}
bool
SearchCombineRequest::CanCombine(const SearchRequestPtr& request) {
if (table_name_ != request->TableName()) {
return false;
}
if (extra_params_ != request->ExtraParams()) {
return false;
}
// topk must within certain range
if (request->TopK() < min_topk_ || request->TopK() > max_topk_) {
return false;
}
// partition list must be equal for each one
std::set<std::string> partition_list;
GetUniqueList(request->PartitionList(), partition_list);
if (!IsSameList(partition_list_, partition_list)) {
return false;
}
// file id list must be equal for each one
std::set<std::string> file_id_list;
GetUniqueList(request->FileIDList(), file_id_list);
if (!IsSameList(file_id_list_, file_id_list)) {
return false;
}
return true;
}
bool
SearchCombineRequest::CanCombine(const SearchRequestPtr& left, const SearchRequestPtr& right) {
if (left->TableName() != right->TableName()) {
return false;
}
if (left->ExtraParams() != right->ExtraParams()) {
return false;
}
// topk must within certain range
if (abs(left->TopK() - right->TopK() > MAX_TOPK_GAP)) {
return false;
}
// partition list must be equal for each one
std::set<std::string> left_partition_list, right_partition_list;
GetUniqueList(left->PartitionList(), left_partition_list);
GetUniqueList(right->PartitionList(), right_partition_list);
if (!IsSameList(left_partition_list, right_partition_list)) {
return false;
}
// file id list must be equal for each one
std::set<std::string> left_file_id_list, right_file_id_list;
GetUniqueList(left->FileIDList(), left_file_id_list);
GetUniqueList(right->FileIDList(), right_file_id_list);
if (!IsSameList(left_file_id_list, right_file_id_list)) {
return false;
}
return true;
}
Status
SearchCombineRequest::FreeRequests(const Status& status) {
for (auto request : request_list_) {
FreeRequest(request, status);
}
return Status::OK();
}
Status
SearchCombineRequest::OnExecute() {
try {
size_t combined_request = request_list_.size();
SERVER_LOG_DEBUG << "SearchCombineRequest begin execute, combined requests=" << combined_request
<< ", extra_params=" << extra_params_.dump();
std::string hdr = "SearchCombineRequest(table=" + table_name_ + ")";
TimeRecorder rc(hdr);
// step 1: check table name
auto status = ValidationUtil::ValidateTableName(table_name_);
if (!status.ok()) {
FreeRequests(status);
return status;
}
// step 2: check table existence
// only process root table, ignore partition table
engine::meta::TableSchema table_schema;
table_schema.table_id_ = table_name_;
status = DBWrapper::DB()->DescribeTable(table_schema);
if (!status.ok()) {
if (status.code() == DB_NOT_FOUND) {
status = Status(SERVER_TABLE_NOT_EXIST, TableNotExistMsg(table_name_));
FreeRequests(status);
return status;
} else {
FreeRequests(status);
return status;
}
} else {
if (!table_schema.owner_table_.empty()) {
status = Status(SERVER_INVALID_TABLE_NAME, TableNotExistMsg(table_name_));
FreeRequests(status);
return status;
}
}
// step 3: check input
size_t run_request = 0;
std::vector<SearchRequestPtr>::iterator iter = request_list_.begin();
for (; iter != request_list_.end();) {
SearchRequestPtr& request = *iter;
status = ValidationUtil::ValidateSearchTopk(request->TopK());
if (!status.ok()) {
// check failed, erase request and let it return error status
FreeRequest(request, status);
iter = request_list_.erase(iter);
continue;
}
status = ValidationUtil::ValidateSearchParams(extra_params_, table_schema, request->TopK());
if (!status.ok()) {
// check failed, erase request and let it return error status
FreeRequest(request, status);
iter = request_list_.erase(iter);
continue;
}
status = ValidationUtil::ValidateVectorData(request->VectorsData(), table_schema);
if (!status.ok()) {
// check failed, erase request and let it return error status
FreeRequest(request, status);
iter = request_list_.erase(iter);
continue;
}
status = ValidationUtil::ValidatePartitionTags(request->PartitionList());
if (!status.ok()) {
// check failed, erase request and let it return error status
FreeRequest(request, status);
iter = request_list_.erase(iter);
continue;
}
// reset topk
search_topk_ = request->TopK() > search_topk_ ? request->TopK() : search_topk_;
// next one
run_request++;
iter++;
}
// all requests are skipped
if (request_list_.empty()) {
SERVER_LOG_DEBUG << "all combined requests were skipped";
return Status::OK();
}
SERVER_LOG_DEBUG << (combined_request - run_request) << " requests were skipped";
SERVER_LOG_DEBUG << "reset topk to " << search_topk_;
rc.RecordSection("check validation");
// step 5: construct vectors_data and set search_topk
SearchRequestPtr& first_request = *request_list_.begin();
uint64_t total_count = 0;
for (auto& request : request_list_) {
total_count += request->VectorsData().vector_count_;
}
vectors_data_.vector_count_ = total_count;
uint16_t dimension = table_schema.dimension_;
bool is_float = true;
if (!first_request->VectorsData().float_data_.empty()) {
vectors_data_.float_data_.resize(total_count * dimension);
} else {
vectors_data_.binary_data_.resize(total_count * dimension / 8);
is_float = false;
}
int64_t offset = 0;
for (auto& request : request_list_) {
const engine::VectorsData& src = request->VectorsData();
size_t data_size = 0;
if (is_float) {
data_size = src.vector_count_ * dimension;
memcpy(vectors_data_.float_data_.data() + offset, src.float_data_.data(), data_size);
} else {
data_size = src.vector_count_ * dimension / 8;
memcpy(vectors_data_.binary_data_.data() + offset, src.binary_data_.data(), data_size);
}
offset += data_size;
}
SERVER_LOG_DEBUG << total_count << " query vectors combined";
// step 6: search vectors
const std::vector<std::string>& partition_list = first_request->PartitionList();
const std::vector<std::string>& file_id_list = first_request->FileIDList();
auto context = first_request->Context();
engine::ResultIds result_ids;
engine::ResultDistances result_distances;
if (file_id_list_.empty()) {
status = DBWrapper::DB()->Query(context, table_name_, partition_list, (size_t)search_topk_, extra_params_,
vectors_data_, result_ids, result_distances);
} else {
status = DBWrapper::DB()->QueryByFileID(context, file_id_list, (size_t)search_topk_, extra_params_,
vectors_data_, result_ids, result_distances);
}
rc.RecordSection("search combined vectors from engine");
if (!status.ok()) {
// let all request return
FreeRequests(status);
return status;
}
if (result_ids.empty()) {
status = Status(DB_ERROR, "no result returned for combined request");
// let all request return
FreeRequests(status);
return status;
}
// step 6: construct result array
offset = 0;
for (auto& request : request_list_) {
uint64_t count = request->VectorsData().vector_count_;
int64_t topk = request->TopK();
uint64_t element_cnt = count * topk;
TopKQueryResult& result = request->QueryResult();
result.id_list_.resize(element_cnt);
result.distance_list_.resize(element_cnt);
memcpy(result.id_list_.data(), result_ids.data() + offset, element_cnt * sizeof(int64_t));
memcpy(result.distance_list_.data(), result_distances.data() + offset, element_cnt * sizeof(float));
offset += (count * search_topk_);
// let request return
FreeRequest(request, Status::OK());
}
rc.RecordSection("construct result and send");
rc.ElapseFromBegin("totally cost");
} catch (std::exception& ex) {
return Status(SERVER_UNEXPECTED_ERROR, ex.what());
}
return Status::OK();
}
} // namespace server
} // namespace milvus

View File

@ -0,0 +1,62 @@
// Copyright (C) 2019-2020 Zilliz. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance
// with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software distributed under the License
// is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
// or implied. See the License for the specific language governing permissions and limitations under the License.
#pragma once
#include "server/delivery/request/BaseRequest.h"
#include "server/delivery/request/SearchRequest.h"
#include <memory>
#include <set>
#include <string>
#include <vector>
namespace milvus {
namespace server {
class SearchCombineRequest : public BaseRequest {
public:
SearchCombineRequest();
Status
Combine(const SearchRequestPtr& request);
bool
CanCombine(const SearchRequestPtr& request);
static bool
CanCombine(const SearchRequestPtr& left, const SearchRequestPtr& right);
protected:
Status
OnExecute() override;
private:
Status
FreeRequests(const Status& status);
private:
std::string table_name_;
engine::VectorsData vectors_data_;
int64_t min_topk_ = 0;
int64_t search_topk_ = 0;
int64_t max_topk_ = 0;
milvus::json extra_params_;
std::set<std::string> partition_list_;
std::set<std::string> file_id_list_;
std::vector<SearchRequestPtr> request_list_;
};
using SearchCombineRequestPtr = std::shared_ptr<SearchCombineRequest>;
} // namespace server
} // namespace milvus

View File

@ -19,6 +19,7 @@
#include <fiu-local.h>
#include <memory>
#ifdef MILVUS_ENABLE_PROFILING
#include <gperftools/profiler.h>
#endif
@ -26,11 +27,11 @@
namespace milvus {
namespace server {
SearchRequest::SearchRequest(const std::shared_ptr<Context>& context, const std::string& table_name,
SearchRequest::SearchRequest(const std::shared_ptr<milvus::server::Context>& context, const std::string& table_name,
const engine::VectorsData& vectors, int64_t topk, const milvus::json& extra_params,
const std::vector<std::string>& partition_list,
const std::vector<std::string>& file_id_list, TopKQueryResult& result)
: BaseRequest(context, DQL_REQUEST_GROUP),
: BaseRequest(context, BaseRequest::kSearch),
table_name_(table_name),
vectors_data_(vectors),
topk_(topk),
@ -41,7 +42,7 @@ SearchRequest::SearchRequest(const std::shared_ptr<Context>& context, const std:
}
BaseRequestPtr
SearchRequest::Create(const std::shared_ptr<Context>& context, const std::string& table_name,
SearchRequest::Create(const std::shared_ptr<milvus::server::Context>& context, const std::string& table_name,
const engine::VectorsData& vectors, int64_t topk, const milvus::json& extra_params,
const std::vector<std::string>& partition_list, const std::vector<std::string>& file_id_list,
TopKQueryResult& result) {
@ -56,8 +57,9 @@ SearchRequest::OnExecute() {
uint64_t vector_count = vectors_data_.vector_count_;
auto pre_query_ctx = context_->Child("Pre query");
SERVER_LOG_DEBUG << "SearchRequest begin execute, extra_params=" << extra_params_.dump();
std::string hdr = "SearchRequest(table=" + table_name_ + ", nq=" + std::to_string(vector_count) +
", k=" + std::to_string(topk_) + ", extra_params=" + extra_params_.dump() + ")";
", k=" + std::to_string(topk_) + ")";
TimeRecorder rc(hdr);
@ -67,7 +69,13 @@ SearchRequest::OnExecute() {
return status;
}
// step 2: check table existence
// step 2: check search topk
status = ValidationUtil::ValidateSearchTopk(topk_);
if (!status.ok()) {
return status;
}
// step 3: check table existence
// only process root table, ignore partition table
engine::meta::TableSchema table_schema;
table_schema.table_id_ = table_name_;
@ -85,54 +93,29 @@ SearchRequest::OnExecute() {
}
}
// step 4: check search parameters
status = ValidationUtil::ValidateSearchParams(extra_params_, table_schema, topk_);
if (!status.ok()) {
return status;
}
// step 3: check search parameter
status = ValidationUtil::ValidateSearchTopk(topk_, table_schema);
// step 5: check vector data according to metric type
status = ValidationUtil::ValidateVectorData(vectors_data_, table_schema);
if (!status.ok()) {
return status;
}
if (vectors_data_.float_data_.empty() && vectors_data_.binary_data_.empty()) {
return Status(SERVER_INVALID_ROWRECORD_ARRAY,
"The vector array is empty. Make sure you have entered vector records.");
// step 6: check partition tags
status = ValidationUtil::ValidatePartitionTags(partition_list_);
fiu_do_on("SearchRequest.OnExecute.invalid_partition_tags",
status = Status(milvus::SERVER_UNEXPECTED_ERROR, ""));
if (!status.ok()) {
return status;
}
rc.RecordSection("check validation");
// step 4: check metric type
if (engine::utils::IsBinaryMetricType(table_schema.metric_type_)) {
// check prepared binary data
if (vectors_data_.binary_data_.size() % vector_count != 0) {
return Status(SERVER_INVALID_ROWRECORD_ARRAY,
"The vector dimension must be equal to the table dimension.");
}
if (vectors_data_.binary_data_.size() * 8 / vector_count != table_schema.dimension_) {
return Status(SERVER_INVALID_VECTOR_DIMENSION,
"The vector dimension must be equal to the table dimension.");
}
} else {
// check prepared float data
fiu_do_on("SearchRequest.OnExecute.invalod_rowrecord_array",
vector_count = vectors_data_.float_data_.size() + 1);
if (vectors_data_.float_data_.size() % vector_count != 0) {
return Status(SERVER_INVALID_ROWRECORD_ARRAY,
"The vector dimension must be equal to the table dimension.");
}
fiu_do_on("SearchRequest.OnExecute.invalid_dim", table_schema.dimension_ = -1);
if (vectors_data_.float_data_.size() / vector_count != table_schema.dimension_) {
return Status(SERVER_INVALID_VECTOR_DIMENSION,
"The vector dimension must be equal to the table dimension.");
}
}
rc.RecordSection("prepare vector data");
// step 5: search vectors
// step 7: search vectors
engine::ResultIds result_ids;
engine::ResultDistances result_distances;
@ -144,13 +127,6 @@ SearchRequest::OnExecute() {
pre_query_ctx->GetTraceContext()->GetSpan()->Finish();
if (file_id_list_.empty()) {
status = ValidationUtil::ValidatePartitionTags(partition_list_);
fiu_do_on("SearchRequest.OnExecute.invalid_partition_tags",
status = Status(milvus::SERVER_UNEXPECTED_ERROR, ""));
if (!status.ok()) {
return status;
}
status = DBWrapper::DB()->Query(context_, table_name_, partition_list_, (size_t)topk_, extra_params_,
vectors_data_, result_ids, result_distances);
} else {
@ -174,14 +150,13 @@ SearchRequest::OnExecute() {
auto post_query_ctx = context_->Child("Constructing result");
// step 7: construct result array
// step 8: construct result array
result_.row_num_ = vector_count;
result_.distance_list_ = result_distances;
result_.id_list_ = result_ids;
post_query_ctx->GetTraceContext()->GetSpan()->Finish();
// step 8: print time cost percent
rc.RecordSection("construct result and send");
rc.ElapseFromBegin("totally cost");
} catch (std::exception& ex) {

View File

@ -23,12 +23,48 @@ namespace server {
class SearchRequest : public BaseRequest {
public:
static BaseRequestPtr
Create(const std::shared_ptr<Context>& context, const std::string& table_name, const engine::VectorsData& vectors,
int64_t topk, const milvus::json& extra_params, const std::vector<std::string>& partition_list,
const std::vector<std::string>& file_id_list, TopKQueryResult& result);
Create(const std::shared_ptr<milvus::server::Context>& context, const std::string& table_name,
const engine::VectorsData& vectors, int64_t topk, const milvus::json& extra_params,
const std::vector<std::string>& partition_list, const std::vector<std::string>& file_id_list,
TopKQueryResult& result);
const std::string&
TableName() const {
return table_name_;
}
const engine::VectorsData&
VectorsData() const {
return vectors_data_;
}
int64_t
TopK() const {
return topk_;
}
const milvus::json&
ExtraParams() const {
return extra_params_;
}
const std::vector<std::string>&
PartitionList() const {
return partition_list_;
}
const std::vector<std::string>&
FileIDList() const {
return file_id_list_;
}
TopKQueryResult&
QueryResult() {
return result_;
}
protected:
SearchRequest(const std::shared_ptr<Context>& context, const std::string& table_name,
SearchRequest(const std::shared_ptr<milvus::server::Context>& context, const std::string& table_name,
const engine::VectorsData& vectors, int64_t topk, const milvus::json& extra_params,
const std::vector<std::string>& partition_list, const std::vector<std::string>& file_id_list,
TopKQueryResult& result);
@ -47,5 +83,7 @@ class SearchRequest : public BaseRequest {
TopKQueryResult& result_;
};
using SearchRequestPtr = std::shared_ptr<SearchRequest>;
} // namespace server
} // namespace milvus

View File

@ -22,13 +22,13 @@
namespace milvus {
namespace server {
ShowPartitionsRequest::ShowPartitionsRequest(const std::shared_ptr<Context>& context, const std::string& table_name,
std::vector<PartitionParam>& partition_list)
: BaseRequest(context, INFO_REQUEST_GROUP), table_name_(table_name), partition_list_(partition_list) {
ShowPartitionsRequest::ShowPartitionsRequest(const std::shared_ptr<milvus::server::Context>& context,
const std::string& table_name, std::vector<PartitionParam>& partition_list)
: BaseRequest(context, BaseRequest::kShowPartitions), table_name_(table_name), partition_list_(partition_list) {
}
BaseRequestPtr
ShowPartitionsRequest::Create(const std::shared_ptr<Context>& context, const std::string& table_name,
ShowPartitionsRequest::Create(const std::shared_ptr<milvus::server::Context>& context, const std::string& table_name,
std::vector<PartitionParam>& partition_list) {
return std::shared_ptr<BaseRequest>(new ShowPartitionsRequest(context, table_name, partition_list));
}

View File

@ -23,11 +23,11 @@ namespace server {
class ShowPartitionsRequest : public BaseRequest {
public:
static BaseRequestPtr
Create(const std::shared_ptr<Context>& context, const std::string& table_name,
Create(const std::shared_ptr<milvus::server::Context>& context, const std::string& table_name,
std::vector<PartitionParam>& partition_list);
protected:
ShowPartitionsRequest(const std::shared_ptr<Context>& context, const std::string& table_name,
ShowPartitionsRequest(const std::shared_ptr<milvus::server::Context>& context, const std::string& table_name,
std::vector<PartitionParam>& partition_list);
Status

View File

@ -43,13 +43,13 @@ ConstructPartitionStat(const engine::PartitionStat& partition_stat, PartitionSta
req_partition_stat.total_row_num_ = row_count;
}
ShowTableInfoRequest::ShowTableInfoRequest(const std::shared_ptr<Context>& context, const std::string& table_name,
TableInfo& table_info)
: BaseRequest(context, INFO_REQUEST_GROUP), table_name_(table_name), table_info_(table_info) {
ShowTableInfoRequest::ShowTableInfoRequest(const std::shared_ptr<milvus::server::Context>& context,
const std::string& table_name, TableInfo& table_info)
: BaseRequest(context, BaseRequest::kShowTableInfo), table_name_(table_name), table_info_(table_info) {
}
BaseRequestPtr
ShowTableInfoRequest::Create(const std::shared_ptr<Context>& context, const std::string& table_name,
ShowTableInfoRequest::Create(const std::shared_ptr<milvus::server::Context>& context, const std::string& table_name,
TableInfo& table_info) {
return std::shared_ptr<BaseRequest>(new ShowTableInfoRequest(context, table_name, table_info));
}

View File

@ -29,10 +29,12 @@ namespace server {
class ShowTableInfoRequest : public BaseRequest {
public:
static BaseRequestPtr
Create(const std::shared_ptr<Context>& context, const std::string& table_name, TableInfo& table_info);
Create(const std::shared_ptr<milvus::server::Context>& context, const std::string& table_name,
TableInfo& table_info);
protected:
ShowTableInfoRequest(const std::shared_ptr<Context>& context, const std::string& table_name, TableInfo& table_info);
ShowTableInfoRequest(const std::shared_ptr<milvus::server::Context>& context, const std::string& table_name,
TableInfo& table_info);
Status
OnExecute() override;

View File

@ -22,12 +22,14 @@
namespace milvus {
namespace server {
ShowTablesRequest::ShowTablesRequest(const std::shared_ptr<Context>& context, std::vector<std::string>& table_name_list)
: BaseRequest(context, INFO_REQUEST_GROUP), table_name_list_(table_name_list) {
ShowTablesRequest::ShowTablesRequest(const std::shared_ptr<milvus::server::Context>& context,
std::vector<std::string>& table_name_list)
: BaseRequest(context, BaseRequest::kShowTables), table_name_list_(table_name_list) {
}
BaseRequestPtr
ShowTablesRequest::Create(const std::shared_ptr<Context>& context, std::vector<std::string>& table_name_list) {
ShowTablesRequest::Create(const std::shared_ptr<milvus::server::Context>& context,
std::vector<std::string>& table_name_list) {
return std::shared_ptr<BaseRequest>(new ShowTablesRequest(context, table_name_list));
}

View File

@ -23,10 +23,11 @@ namespace server {
class ShowTablesRequest : public BaseRequest {
public:
static BaseRequestPtr
Create(const std::shared_ptr<Context>& context, std::vector<std::string>& table_name_list);
Create(const std::shared_ptr<milvus::server::Context>& context, std::vector<std::string>& table_name_list);
protected:
ShowTablesRequest(const std::shared_ptr<Context>& context, std::vector<std::string>& table_name_list);
ShowTablesRequest(const std::shared_ptr<milvus::server::Context>& context,
std::vector<std::string>& table_name_list);
Status
OnExecute() override;

View File

@ -0,0 +1,39 @@
// Copyright (C) 2019-2020 Zilliz. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance
// with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software distributed under the License
// is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
// or implied. See the License for the specific language governing permissions and limitations under the License.
#pragma once
#include "server/delivery/request/BaseRequest.h"
#include "utils/BlockingQueue.h"
#include "utils/Status.h"
#include <memory>
#include <queue>
#include <string>
#include <utility>
#include <vector>
namespace milvus {
namespace server {
class RequestStrategy {
protected:
RequestStrategy() = default;
public:
virtual Status
ReScheduleQueue(const BaseRequestPtr& request, std::queue<BaseRequestPtr>& queue) = 0;
};
using RequestStrategyPtr = std::shared_ptr<RequestStrategy>;
} // namespace server
} // namespace milvus

View File

@ -0,0 +1,77 @@
// Copyright (C) 2019-2020 Zilliz. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance
// with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software distributed under the License
// is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
// or implied. See the License for the specific language governing permissions and limitations under the License.
#include "server/delivery/strategy/SearchReqStrategy.h"
#include "server/delivery/request/SearchCombineRequest.h"
#include "server/delivery/request/SearchRequest.h"
#include "utils/CommonUtil.h"
#include "utils/Error.h"
#include "utils/Log.h"
#include "utils/TimeRecorder.h"
#include <queue>
#include <string>
namespace milvus {
namespace server {
SearchReqStrategy::SearchReqStrategy() {
}
Status
SearchReqStrategy::ReScheduleQueue(const BaseRequestPtr& request, std::queue<BaseRequestPtr>& queue) {
if (request->GetRequestType() != BaseRequest::kSearch) {
std::string msg = "search strategy can only handle search request";
SERVER_LOG_ERROR << msg;
return Status(SERVER_UNSUPPORTED_ERROR, msg);
}
// TimeRecorderAuto rc("SearchReqStrategy::ReScheduleQueue");
SearchRequestPtr new_search_req = std::static_pointer_cast<SearchRequest>(request);
BaseRequestPtr last_req = queue.back();
if (last_req->GetRequestType() == BaseRequest::kSearch) {
SearchRequestPtr last_search_req = std::static_pointer_cast<SearchRequest>(last_req);
if (SearchCombineRequest::CanCombine(last_search_req, new_search_req)) {
// pop last request
queue.pop();
// combine request
SearchCombineRequestPtr combine_request = std::make_shared<SearchCombineRequest>();
combine_request->Combine(last_search_req);
combine_request->Combine(new_search_req);
queue.push(combine_request);
SERVER_LOG_DEBUG << "Combine 2 search request";
} else {
// directly put to queue
queue.push(request);
}
} else if (last_req->GetRequestType() == BaseRequest::kSearchCombine) {
SearchCombineRequestPtr combine_req = std::static_pointer_cast<SearchCombineRequest>(last_req);
if (combine_req->CanCombine(new_search_req)) {
// combine request
combine_req->Combine(new_search_req);
SERVER_LOG_DEBUG << "Combine more search request";
} else {
// directly put to queue
queue.push(request);
}
} else {
std::string msg = "unsupported request type for search strategy";
SERVER_LOG_ERROR << msg;
return Status(SERVER_UNSUPPORTED_ERROR, msg);
}
return Status::OK();
}
} // namespace server
} // namespace milvus

View File

@ -0,0 +1,33 @@
// Copyright (C) 2019-2020 Zilliz. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance
// with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software distributed under the License
// is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
// or implied. See the License for the specific language governing permissions and limitations under the License.
#pragma once
#include "server/delivery/strategy/RequestStrategy.h"
#include "utils/Status.h"
#include <memory>
#include <queue>
namespace milvus {
namespace server {
class SearchReqStrategy : public RequestStrategy {
public:
SearchReqStrategy();
Status
ReScheduleQueue(const BaseRequestPtr& request, std::queue<BaseRequestPtr>& queue) override;
};
using RequestStrategyPtr = std::shared_ptr<RequestStrategy>;
} // namespace server
} // namespace milvus

View File

@ -26,6 +26,9 @@ class BlockingQueue {
BlockingQueue() : mtx(), full_(), empty_() {
}
virtual ~BlockingQueue() {
}
BlockingQueue(const BlockingQueue& rhs) = delete;
BlockingQueue&
@ -52,7 +55,7 @@ class BlockingQueue {
void
SetCapacity(const size_t capacity);
private:
protected:
mutable std::mutex mtx;
std::condition_variable full_;
std::condition_variable empty_;

View File

@ -306,6 +306,39 @@ ValidationUtil::ValidateSearchParams(const milvus::json& search_params, const en
return Status::OK();
}
Status
ValidationUtil::ValidateVectorData(const engine::VectorsData& vectors, const engine::meta::TableSchema& table_schema) {
if (vectors.float_data_.empty() && vectors.binary_data_.empty()) {
return Status(SERVER_INVALID_ROWRECORD_ARRAY,
"The vector array is empty. Make sure you have entered vector records.");
}
uint64_t vector_count = vectors.vector_count_;
if (engine::utils::IsBinaryMetricType(table_schema.metric_type_)) {
// check prepared binary data
if (vectors.binary_data_.size() % vector_count != 0) {
return Status(SERVER_INVALID_ROWRECORD_ARRAY, "The vector dimension must be equal to the table dimension.");
}
if (vectors.binary_data_.size() * 8 / vector_count != table_schema.dimension_) {
return Status(SERVER_INVALID_VECTOR_DIMENSION,
"The vector dimension must be equal to the table dimension.");
}
} else {
// check prepared float data
fiu_do_on("SearchRequest.OnExecute.invalod_rowrecord_array", vector_count = vectors.float_data_.size() + 1);
if (vectors.float_data_.size() % vector_count != 0) {
return Status(SERVER_INVALID_ROWRECORD_ARRAY, "The vector dimension must be equal to the table dimension.");
}
if (vectors.float_data_.size() / vector_count != table_schema.dimension_) {
return Status(SERVER_INVALID_VECTOR_DIMENSION,
"The vector dimension must be equal to the table dimension.");
}
}
return Status::OK();
}
Status
ValidationUtil::ValidateTableIndexFileSize(int64_t index_file_size) {
if (index_file_size <= 0 || index_file_size > INDEX_FILE_SIZE_LIMIT) {
@ -331,8 +364,8 @@ ValidationUtil::ValidateTableIndexMetricType(int32_t metric_type) {
}
Status
ValidationUtil::ValidateSearchTopk(int64_t top_k, const engine::meta::TableSchema& table_schema) {
if (top_k <= 0 || top_k > 2048) {
ValidationUtil::ValidateSearchTopk(int64_t top_k) {
if (top_k <= 0 || top_k > QUERY_MAX_TOPK) {
std::string msg =
"Invalid topk: " + std::to_string(top_k) + ". " + "The topk must be within the range of 1 ~ 2048.";
SERVER_LOG_ERROR << msg;

View File

@ -11,6 +11,7 @@
#pragma once
#include "db/Types.h"
#include "db/meta/MetaTypes.h"
#include "utils/Json.h"
#include "utils/Status.h"
@ -21,6 +22,8 @@
namespace milvus {
namespace server {
constexpr int64_t QUERY_MAX_TOPK = 2048;
class ValidationUtil {
private:
ValidationUtil() = default;
@ -43,6 +46,9 @@ class ValidationUtil {
ValidateSearchParams(const milvus::json& search_params, const engine::meta::TableSchema& table_schema,
int64_t topk);
static Status
ValidateVectorData(const engine::VectorsData& vectors, const engine::meta::TableSchema& table_schema);
static Status
ValidateTableIndexFileSize(int64_t index_file_size);
@ -50,7 +56,7 @@ class ValidationUtil {
ValidateTableIndexMetricType(int32_t metric_type);
static Status
ValidateSearchTopk(int64_t top_k, const engine::meta::TableSchema& table_schema);
ValidateSearchTopk(int64_t top_k);
static Status
ValidatePartitionName(const std::string& partition_name);

View File

@ -89,9 +89,11 @@ set(web_server_files
aux_source_directory(${MILVUS_ENGINE_SRC}/server/delivery server_delivery_impl_files)
aux_source_directory(${MILVUS_ENGINE_SRC}/server/delivery/request server_delivery_request_files)
aux_source_directory(${MILVUS_ENGINE_SRC}/server/delivery/strategy server_delivery_strategy_files)
set(server_delivery_files
${server_delivery_impl_files}
${server_delivery_request_files})
${server_delivery_request_files}
${server_delivery_strategy_files})
aux_source_directory(${MILVUS_ENGINE_SRC}/utils utils_files)
aux_source_directory(${MILVUS_ENGINE_SRC}/index/archive wrapper_files)

View File

@ -709,13 +709,14 @@ class DummyRequest : public milvus::server::BaseRequest {
}
static milvus::server::BaseRequestPtr
Create(std::string& dummy) {
return std::shared_ptr<milvus::server::BaseRequest>(new DummyRequest(dummy));
Create() {
return std::shared_ptr<milvus::server::BaseRequest>(new DummyRequest());
}
public:
explicit DummyRequest(std::string& dummy)
: BaseRequest(std::make_shared<milvus::server::Context>("dummy_request_id"), dummy) {
DummyRequest()
: BaseRequest(std::make_shared<milvus::server::Context>("dummy_request_id"),
milvus::server::BaseRequest::kCmd) {
}
};
@ -723,8 +724,7 @@ class RpcSchedulerTest : public testing::Test {
protected:
void
SetUp() override {
std::string dummy = "dql";
request_ptr = std::make_shared<DummyRequest>(dummy);
request_ptr = std::make_shared<DummyRequest>();
}
std::shared_ptr<DummyRequest> request_ptr;
@ -738,17 +738,15 @@ class AsyncDummyRequest : public milvus::server::BaseRequest {
}
static milvus::server::BaseRequestPtr
Create(std::string& dummy) {
return std::shared_ptr<milvus::server::BaseRequest>(new DummyRequest(dummy));
}
void TestSetStatus() {
SetStatus(milvus::SERVER_INVALID_ARGUMENT, "");
Create() {
return std::shared_ptr<milvus::server::BaseRequest>(new DummyRequest());
}
public:
explicit AsyncDummyRequest(std::string& dummy)
: BaseRequest(std::make_shared<milvus::server::Context>("dummy_request_id2"), dummy, true) {
AsyncDummyRequest()
: BaseRequest(std::make_shared<milvus::server::Context>("dummy_request_id2"),
milvus::server::BaseRequest::kCmd,
true) {
}
};
} // namespace
@ -761,8 +759,7 @@ TEST_F(RpcSchedulerTest, BASE_TASK_TEST) {
// milvus::server::RequestScheduler::GetInstance().Stop();
// milvus::server::RequestScheduler::GetInstance().Start();
std::string dummy = "dql";
milvus::server::BaseRequestPtr base_task_ptr = DummyRequest::Create(dummy);
milvus::server::BaseRequestPtr base_task_ptr = DummyRequest::Create();
milvus::server::RequestScheduler::ExecRequest(base_task_ptr);
milvus::server::RequestScheduler::GetInstance().ExecuteRequest(request_ptr);
@ -778,20 +775,17 @@ TEST_F(RpcSchedulerTest, BASE_TASK_TEST) {
// milvus::server::RequestScheduler::GetInstance().ExecuteRequest(base_task_ptr2);
// fiu_disable("RequestScheduler.PutToQueue.null_queue");
std::string dummy3 = "dql3";
milvus::server::BaseRequestPtr base_task_ptr3 = DummyRequest::Create(dummy3);
milvus::server::BaseRequestPtr base_task_ptr3 = DummyRequest::Create();
fiu_enable("RequestScheduler.TakeToExecute.throw_std_exception", 1, NULL, 0);
milvus::server::RequestScheduler::GetInstance().ExecuteRequest(base_task_ptr3);
fiu_disable("RequestScheduler.TakeToExecute.throw_std_exception");
std::string dummy4 = "dql4";
milvus::server::BaseRequestPtr base_task_ptr4 = DummyRequest::Create(dummy4);
milvus::server::BaseRequestPtr base_task_ptr4 = DummyRequest::Create();
fiu_enable("RequestScheduler.TakeToExecute.execute_fail", 1, NULL, 0);
milvus::server::RequestScheduler::GetInstance().ExecuteRequest(base_task_ptr4);
fiu_disable("RequestScheduler.TakeToExecute.execute_fail");
std::string dummy5 = "dql5";
milvus::server::BaseRequestPtr base_task_ptr5 = DummyRequest::Create(dummy5);
milvus::server::BaseRequestPtr base_task_ptr5 = DummyRequest::Create();
fiu_enable("RequestScheduler.PutToQueue.push_null_thread", 1, NULL, 0);
milvus::server::RequestScheduler::GetInstance().ExecuteRequest(base_task_ptr5);
fiu_disable("RequestScheduler.PutToQueue.push_null_thread");
@ -802,11 +796,10 @@ TEST_F(RpcSchedulerTest, BASE_TASK_TEST) {
milvus::server::BaseRequestPtr null_ptr = nullptr;
milvus::server::RequestScheduler::ExecRequest(null_ptr);
std::string async_dummy = "AsyncDummyRequest";
auto async_ptr = std::make_shared<AsyncDummyRequest>(async_dummy);
auto async_ptr = std::make_shared<AsyncDummyRequest>();
auto base_ptr = std::static_pointer_cast<milvus::server::BaseRequest>(async_ptr);
milvus::server::RequestScheduler::ExecRequest(base_ptr);
async_ptr->TestSetStatus();
async_ptr->set_status(milvus::Status(milvus::SERVER_INVALID_ARGUMENT, ""));
milvus::server::RequestScheduler::GetInstance().Stop();
milvus::server::RequestScheduler::GetInstance().Start();

View File

@ -623,10 +623,9 @@ TEST(ValidationUtilTest, VALIDATE_SEARCH_PARAMS_TEST) {
}
TEST(ValidationUtilTest, VALIDATE_TOPK_TEST) {
milvus::engine::meta::TableSchema schema;
ASSERT_EQ(milvus::server::ValidationUtil::ValidateSearchTopk(10, schema).code(), milvus::SERVER_SUCCESS);
ASSERT_NE(milvus::server::ValidationUtil::ValidateSearchTopk(65536, schema).code(), milvus::SERVER_SUCCESS);
ASSERT_NE(milvus::server::ValidationUtil::ValidateSearchTopk(0, schema).code(), milvus::SERVER_SUCCESS);
ASSERT_EQ(milvus::server::ValidationUtil::ValidateSearchTopk(10).code(), milvus::SERVER_SUCCESS);
ASSERT_NE(milvus::server::ValidationUtil::ValidateSearchTopk(65536).code(), milvus::SERVER_SUCCESS);
ASSERT_NE(milvus::server::ValidationUtil::ValidateSearchTopk(0).code(), milvus::SERVER_SUCCESS);
}
TEST(ValidationUtilTest, VALIDATE_PARTITION_TAGS) {