GrpcRequestTask.cpp 34.7 KB
Newer Older
K
kun yu 已提交
1
/*******************************************************************************
Y
Yu Kun 已提交
2 3 4 5
* Copyright 上海赜睿信息科技有限公司(Zilliz) - All Rights Reserved
* Unauthorized copying of this file, via any medium is strictly prohibited.
* Proprietary and confidential.
******************************************************************************/
Y
Yu Kun 已提交
6
#include "GrpcRequestTask.h"
K
kun yu 已提交
7
#include "../ServerConfig.h"
K
kun yu 已提交
8 9 10 11
#include "utils/CommonUtil.h"
#include "utils/Log.h"
#include "utils/TimeRecorder.h"
#include "utils/ValidationUtil.h"
K
kun yu 已提交
12
#include "../DBWrapper.h"
K
kun yu 已提交
13
#include "version.h"
Y
Yu Kun 已提交
14
#include "GrpcMilvusServer.h"
S
starlord 已提交
15
#include "db/Utils.h"
16
#include "scheduler/SchedInst.h"
Y
Yu Kun 已提交
17
#include <gperftools/profiler.h>
K
kun yu 已提交
18

K
kun yu 已提交
19
#include "src/server/Server.h"
K
kun yu 已提交
20

S
starlord 已提交
21 22
#include <string.h>

K
kun yu 已提交
23 24 25
namespace zilliz {
namespace milvus {
namespace server {
Y
Yu Kun 已提交
26 27 28 29 30
namespace grpc {

static const char *DQL_TASK_GROUP = "dql";
static const char *DDL_DML_TASK_GROUP = "ddl_dml";
static const char *PING_TASK_GROUP = "ping";
K
kun yu 已提交
31 32 33 34 35 36 37 38 39 40 41 42 43

using DB_META = zilliz::milvus::engine::meta::Meta;
using DB_DATE = zilliz::milvus::engine::meta::DateT;

namespace {
    engine::EngineType EngineType(int type) {
        static std::map<int, engine::EngineType> map_type = {
                {0, engine::EngineType::INVALID},
                {1, engine::EngineType::FAISS_IDMAP},
                {2, engine::EngineType::FAISS_IVFFLAT},
                {3, engine::EngineType::FAISS_IVFSQ8},
        };

Y
Yu Kun 已提交
44
        if (map_type.find(type) == map_type.end()) {
K
kun yu 已提交
45 46 47 48 49 50 51 52
            return engine::EngineType::INVALID;
        }

        return map_type[type];
    }

    int IndexType(engine::EngineType type) {
        static std::map<engine::EngineType, int> map_type = {
Y
Yu Kun 已提交
53 54
                {engine::EngineType::INVALID,       0},
                {engine::EngineType::FAISS_IDMAP,   1},
K
kun yu 已提交
55
                {engine::EngineType::FAISS_IVFFLAT, 2},
Y
Yu Kun 已提交
56
                {engine::EngineType::FAISS_IVFSQ8,  3},
K
kun yu 已提交
57 58
        };

Y
Yu Kun 已提交
59
        if (map_type.find(type) == map_type.end()) {
K
kun yu 已提交
60 61 62 63 64 65
            return 0;
        }

        return map_type[type];
    }

K
kun yu 已提交
66
    constexpr long DAY_SECONDS = 24 * 60 * 60;
K
kun yu 已提交
67 68 69

    void
    ConvertTimeRangeToDBDates(const std::vector<::milvus::grpc::Range> &range_array,
Y
Yu Kun 已提交
70 71 72
                              std::vector<DB_DATE> &dates,
                              ServerError &error_code,
                              std::string &error_msg) {
K
kun yu 已提交
73
        dates.clear();
Y
Yu Kun 已提交
74
        for (auto &range : range_array) {
K
kun yu 已提交
75 76
            time_t tt_start, tt_end;
            tm tm_start, tm_end;
Y
Yu Kun 已提交
77
            if (!CommonUtil::TimeStrToTime(range.start_value(), tt_start, tm_start)) {
K
kun yu 已提交
78 79 80 81 82
                error_code = SERVER_INVALID_TIME_RANGE;
                error_msg = "Invalid time range: " + range.start_value();
                return;
            }

Y
Yu Kun 已提交
83
            if (!CommonUtil::TimeStrToTime(range.end_value(), tt_end, tm_end)) {
K
kun yu 已提交
84 85 86 87 88
                error_code = SERVER_INVALID_TIME_RANGE;
                error_msg = "Invalid time range: " + range.start_value();
                return;
            }

Y
Yu Kun 已提交
89 90 91
            long days = (tt_end > tt_start) ? (tt_end - tt_start) / DAY_SECONDS : (tt_start - tt_end) /
                                                                                  DAY_SECONDS;
            if (days == 0) {
K
kun yu 已提交
92 93
                error_code = SERVER_INVALID_TIME_RANGE;
                error_msg = "Invalid time range: " + range.start_value() + " to " + range.end_value();
Y
Yu Kun 已提交
94
                return;
K
kun yu 已提交
95 96
            }

97
            //range: [start_day, end_day)
Y
Yu Kun 已提交
98 99
            for (long i = 0; i < days; i++) {
                time_t tt_day = tt_start + DAY_SECONDS * i;
K
kun yu 已提交
100 101 102
                tm tm_day;
                CommonUtil::ConvertTime(tt_day, tm_day);

Y
Yu Kun 已提交
103 104
                long date = tm_day.tm_year * 10000 + tm_day.tm_mon * 100 +
                            tm_day.tm_mday;//according to db logic
K
kun yu 已提交
105 106 107 108 109 110 111
                dates.push_back(date);
            }
        }
    }
}

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
S
starlord 已提交
112
CreateTableTask::CreateTableTask(const ::milvus::grpc::TableSchema *schema)
Y
Yu Kun 已提交
113
        : GrpcBaseTask(DDL_DML_TASK_GROUP),
K
kun yu 已提交
114 115 116 117
          schema_(schema) {

}

Y
Yu Kun 已提交
118
BaseTaskPtr
S
starlord 已提交
119 120 121 122 123
CreateTableTask::Create(const ::milvus::grpc::TableSchema *schema) {
    if(schema == nullptr) {
        SERVER_LOG_ERROR << "grpc input is null!";
        return nullptr;
    }
Y
Yu Kun 已提交
124
    return std::shared_ptr<GrpcBaseTask>(new CreateTableTask(schema));
K
kun yu 已提交
125 126
}

Y
Yu Kun 已提交
127 128
ServerError
CreateTableTask::OnExecute() {
K
kun yu 已提交
129 130 131 132
    TimeRecorder rc("CreateTableTask");

    try {
        //step 1: check arguments
S
starlord 已提交
133
        ServerError res = ValidationUtil::ValidateTableName(schema_->table_name().table_name());
Y
Yu Kun 已提交
134
        if (res != SERVER_SUCCESS) {
S
starlord 已提交
135
            return SetError(res, "Invalid table name: " + schema_->table_name().table_name());
K
kun yu 已提交
136 137
        }

S
starlord 已提交
138
        res = ValidationUtil::ValidateTableDimension(schema_->dimension());
Y
Yu Kun 已提交
139
        if (res != SERVER_SUCCESS) {
S
starlord 已提交
140
            return SetError(res, "Invalid table dimension: " + std::to_string(schema_->dimension()));
K
kun yu 已提交
141 142
        }

S
starlord 已提交
143
        res = ValidationUtil::ValidateTableIndexFileSize(schema_->index_file_size());
144
        if(res != SERVER_SUCCESS) {
S
starlord 已提交
145
            return SetError(res, "Invalid index file size: " + std::to_string(schema_->index_file_size()));
146 147
        }

S
starlord 已提交
148 149 150 151 152
        res = ValidationUtil::ValidateTableIndexMetricType(schema_->metric_type());
        if(res != SERVER_SUCCESS) {
            return SetError(res, "Invalid index metric type: " + std::to_string(schema_->metric_type()));
        }

K
kun yu 已提交
153 154
        //step 2: construct table schema
        engine::meta::TableSchema table_info;
S
starlord 已提交
155 156 157
        table_info.table_id_ = schema_->table_name().table_name();
        table_info.dimension_ = (uint16_t) schema_->dimension();
        table_info.index_file_size_ = schema_->index_file_size();
S
starlord 已提交
158
        table_info.metric_type_ = schema_->metric_type();
K
kun yu 已提交
159 160 161

        //step 3: create table
        engine::Status stat = DBWrapper::DB()->CreateTable(table_info);
Y
Yu Kun 已提交
162
        if (!stat.ok()) {
K
kun yu 已提交
163
            //table could exist
164 165 166 167
            if(stat.IsAlreadyExist()) {
                return SetError(SERVER_INVALID_TABLE_NAME, stat.ToString());
            }
            return SetError(DB_META_TRANSACTION_FAILED, stat.ToString());
K
kun yu 已提交
168 169
        }

Y
Yu Kun 已提交
170
    } catch (std::exception &ex) {
K
kun yu 已提交
171 172 173
        return SetError(SERVER_UNEXPECTED_ERROR, ex.what());
    }

K
kun yu 已提交
174
    rc.ElapseFromBegin("totally cost");
K
kun yu 已提交
175 176 177 178 179

    return SERVER_SUCCESS;
}

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
S
starlord 已提交
180
DescribeTableTask::DescribeTableTask(const std::string &table_name, ::milvus::grpc::TableSchema *schema)
Y
Yu Kun 已提交
181
        : GrpcBaseTask(DDL_DML_TASK_GROUP),
K
kun yu 已提交
182 183 184 185
          table_name_(table_name),
          schema_(schema) {
}

Y
Yu Kun 已提交
186
BaseTaskPtr
S
starlord 已提交
187
DescribeTableTask::Create(const std::string &table_name, ::milvus::grpc::TableSchema *schema) {
Y
Yu Kun 已提交
188
    return std::shared_ptr<GrpcBaseTask>(new DescribeTableTask(table_name, schema));
K
kun yu 已提交
189 190
}

Y
Yu Kun 已提交
191 192
ServerError
DescribeTableTask::OnExecute() {
K
kun yu 已提交
193 194 195 196
    TimeRecorder rc("DescribeTableTask");

    try {
        //step 1: check arguments
K
kun yu 已提交
197
        ServerError res = ValidationUtil::ValidateTableName(table_name_);
Y
Yu Kun 已提交
198
        if (res != SERVER_SUCCESS) {
K
kun yu 已提交
199 200 201 202 203 204 205
            return SetError(res, "Invalid table name: " + table_name_);
        }

        //step 2: get table info
        engine::meta::TableSchema table_info;
        table_info.table_id_ = table_name_;
        engine::Status stat = DBWrapper::DB()->DescribeTable(table_info);
Y
Yu Kun 已提交
206
        if (!stat.ok()) {
207
            return SetError(DB_META_TRANSACTION_FAILED, stat.ToString());
K
kun yu 已提交
208 209
        }

S
starlord 已提交
210 211
        schema_->mutable_table_name()->set_table_name(table_info.table_id_);
        schema_->set_dimension(table_info.dimension_);
212
        schema_->set_index_file_size(table_info.index_file_size_);
S
starlord 已提交
213
        schema_->set_metric_type(table_info.metric_type_);
K
kun yu 已提交
214

Y
Yu Kun 已提交
215
    } catch (std::exception &ex) {
K
kun yu 已提交
216 217 218
        return SetError(SERVER_UNEXPECTED_ERROR, ex.what());
    }

K
kun yu 已提交
219
    rc.ElapseFromBegin("totally cost");
K
kun yu 已提交
220 221 222 223 224

    return SERVER_SUCCESS;
}

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
S
starlord 已提交
225
CreateIndexTask::CreateIndexTask(const ::milvus::grpc::IndexParam *index_param)
Y
Yu Kun 已提交
226
        : GrpcBaseTask(DDL_DML_TASK_GROUP),
Y
Yu Kun 已提交
227
          index_param_(index_param) {
K
kun yu 已提交
228 229
}

Y
Yu Kun 已提交
230
BaseTaskPtr
S
starlord 已提交
231 232 233 234 235
CreateIndexTask::Create(const ::milvus::grpc::IndexParam *index_param) {
    if(index_param == nullptr) {
        SERVER_LOG_ERROR << "grpc input is null!";
        return nullptr;
    }
Y
Yu Kun 已提交
236
    return std::shared_ptr<GrpcBaseTask>(new CreateIndexTask(index_param));
K
kun yu 已提交
237 238
}

Y
Yu Kun 已提交
239
ServerError
Y
Yu Kun 已提交
240
CreateIndexTask::OnExecute() {
K
kun yu 已提交
241
    try {
Y
Yu Kun 已提交
242
        TimeRecorder rc("CreateIndexTask");
K
kun yu 已提交
243 244

        //step 1: check arguments
S
starlord 已提交
245
        std::string table_name_ = index_param_->table_name().table_name();
K
kun yu 已提交
246
        ServerError res = ValidationUtil::ValidateTableName(table_name_);
Y
Yu Kun 已提交
247
        if (res != SERVER_SUCCESS) {
K
kun yu 已提交
248 249 250 251 252
            return SetError(res, "Invalid table name: " + table_name_);
        }

        bool has_table = false;
        engine::Status stat = DBWrapper::DB()->HasTable(table_name_, has_table);
Y
Yu Kun 已提交
253
        if (!stat.ok()) {
254
            return SetError(DB_META_TRANSACTION_FAILED, stat.ToString());
K
kun yu 已提交
255 256
        }

Y
Yu Kun 已提交
257
        if (!has_table) {
K
kun yu 已提交
258 259 260
            return SetError(SERVER_TABLE_NOT_EXIST, "Table " + table_name_ + " not exists");
        }

S
starlord 已提交
261 262
        auto &grpc_index = index_param_->index();
        res = ValidationUtil::ValidateTableIndexType(grpc_index.index_type());
S
starlord 已提交
263
        if(res != SERVER_SUCCESS) {
S
starlord 已提交
264
            return SetError(res, "Invalid index type: " + std::to_string(grpc_index.index_type()));
S
starlord 已提交
265 266
        }

S
starlord 已提交
267
        res = ValidationUtil::ValidateTableIndexNlist(grpc_index.nlist());
S
starlord 已提交
268
        if(res != SERVER_SUCCESS) {
S
starlord 已提交
269
            return SetError(res, "Invalid index nlist: " + std::to_string(grpc_index.nlist()));
S
starlord 已提交
270 271
        }

K
kun yu 已提交
272
        //step 2: check table existence
273
        engine::TableIndex index;
S
starlord 已提交
274 275
        index.engine_type_ = grpc_index.index_type();
        index.nlist_ = grpc_index.nlist();
276
        stat = DBWrapper::DB()->CreateIndex(table_name_, index);
Y
Yu Kun 已提交
277
        if (!stat.ok()) {
278
            return SetError(SERVER_BUILD_INDEX_ERROR, stat.ToString());
K
kun yu 已提交
279 280
        }

K
kun yu 已提交
281
        rc.ElapseFromBegin("totally cost");
Y
Yu Kun 已提交
282
    } catch (std::exception &ex) {
K
kun yu 已提交
283 284 285 286 287 288 289
        return SetError(SERVER_UNEXPECTED_ERROR, ex.what());
    }

    return SERVER_SUCCESS;
}

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
Y
Yu Kun 已提交
290
HasTableTask::HasTableTask(const std::string &table_name, bool &has_table)
Y
Yu Kun 已提交
291
        : GrpcBaseTask(DDL_DML_TASK_GROUP),
K
kun yu 已提交
292 293 294 295 296
          table_name_(table_name),
          has_table_(has_table) {

}

Y
Yu Kun 已提交
297
BaseTaskPtr
Y
Yu Kun 已提交
298
HasTableTask::Create(const std::string &table_name, bool &has_table) {
Y
Yu Kun 已提交
299
    return std::shared_ptr<GrpcBaseTask>(new HasTableTask(table_name, has_table));
K
kun yu 已提交
300 301
}

Y
Yu Kun 已提交
302 303
ServerError
HasTableTask::OnExecute() {
K
kun yu 已提交
304 305 306 307
    try {
        TimeRecorder rc("HasTableTask");

        //step 1: check arguments
K
kun yu 已提交
308
        ServerError res = ValidationUtil::ValidateTableName(table_name_);
Y
Yu Kun 已提交
309
        if (res != SERVER_SUCCESS) {
K
kun yu 已提交
310 311 312 313 314
            return SetError(res, "Invalid table name: " + table_name_);
        }

        //step 2: check table existence
        engine::Status stat = DBWrapper::DB()->HasTable(table_name_, has_table_);
Y
Yu Kun 已提交
315
        if (!stat.ok()) {
316
            return SetError(DB_META_TRANSACTION_FAILED, stat.ToString());
K
kun yu 已提交
317 318
        }

K
kun yu 已提交
319
        rc.ElapseFromBegin("totally cost");
Y
Yu Kun 已提交
320
    } catch (std::exception &ex) {
K
kun yu 已提交
321 322 323 324 325 326 327
        return SetError(SERVER_UNEXPECTED_ERROR, ex.what());
    }

    return SERVER_SUCCESS;
}

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
Y
Yu Kun 已提交
328
DropTableTask::DropTableTask(const std::string &table_name)
Y
Yu Kun 已提交
329
        : GrpcBaseTask(DDL_DML_TASK_GROUP),
K
kun yu 已提交
330 331 332 333
          table_name_(table_name) {

}

Y
Yu Kun 已提交
334
BaseTaskPtr
Y
Yu Kun 已提交
335
DropTableTask::Create(const std::string &table_name) {
Y
Yu Kun 已提交
336
    return std::shared_ptr<GrpcBaseTask>(new DropTableTask(table_name));
K
kun yu 已提交
337 338
}

Y
Yu Kun 已提交
339 340
ServerError
DropTableTask::OnExecute() {
K
kun yu 已提交
341 342 343 344
    try {
        TimeRecorder rc("DropTableTask");

        //step 1: check arguments
K
kun yu 已提交
345
        ServerError res = ValidationUtil::ValidateTableName(table_name_);
Y
Yu Kun 已提交
346
        if (res != SERVER_SUCCESS) {
K
kun yu 已提交
347 348 349 350 351 352 353
            return SetError(res, "Invalid table name: " + table_name_);
        }

        //step 2: check table existence
        engine::meta::TableSchema table_info;
        table_info.table_id_ = table_name_;
        engine::Status stat = DBWrapper::DB()->DescribeTable(table_info);
Y
Yu Kun 已提交
354 355
        if (!stat.ok()) {
            if (stat.IsNotFound()) {
K
kun yu 已提交
356 357
                return SetError(SERVER_TABLE_NOT_EXIST, "Table " + table_name_ + " not exists");
            } else {
358
                return SetError(DB_META_TRANSACTION_FAILED, stat.ToString());
K
kun yu 已提交
359 360 361
            }
        }

K
kun yu 已提交
362
        rc.ElapseFromBegin("check validation");
K
kun yu 已提交
363 364 365 366

        //step 3: Drop table
        std::vector<DB_DATE> dates;
        stat = DBWrapper::DB()->DeleteTable(table_name_, dates);
Y
Yu Kun 已提交
367
        if (!stat.ok()) {
368
            return SetError(DB_META_TRANSACTION_FAILED, stat.ToString());
K
kun yu 已提交
369 370
        }

K
kun yu 已提交
371
        rc.ElapseFromBegin("total cost");
Y
Yu Kun 已提交
372
    } catch (std::exception &ex) {
K
kun yu 已提交
373 374 375 376 377 378 379
        return SetError(SERVER_UNEXPECTED_ERROR, ex.what());
    }

    return SERVER_SUCCESS;
}

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
S
starlord 已提交
380
ShowTablesTask::ShowTablesTask(::grpc::ServerWriter<::milvus::grpc::TableName> *writer)
Y
Yu Kun 已提交
381
        : GrpcBaseTask(DDL_DML_TASK_GROUP),
K
kun yu 已提交
382 383 384 385
          writer_(writer) {

}

Y
Yu Kun 已提交
386
BaseTaskPtr
S
starlord 已提交
387
ShowTablesTask::Create(::grpc::ServerWriter<::milvus::grpc::TableName> *writer) {
Y
Yu Kun 已提交
388
    return std::shared_ptr<GrpcBaseTask>(new ShowTablesTask(writer));
K
kun yu 已提交
389 390
}

Y
Yu Kun 已提交
391 392
ServerError
ShowTablesTask::OnExecute() {
K
kun yu 已提交
393 394
    std::vector<engine::meta::TableSchema> schema_array;
    engine::Status stat = DBWrapper::DB()->AllTables(schema_array);
Y
Yu Kun 已提交
395
    if (!stat.ok()) {
396
        return SetError(DB_META_TRANSACTION_FAILED, stat.ToString());
K
kun yu 已提交
397 398
    }

Y
Yu Kun 已提交
399
    for (auto &schema : schema_array) {
K
kun yu 已提交
400 401
        ::milvus::grpc::TableName tableName;
        tableName.set_table_name(schema.table_id_);
S
starlord 已提交
402
        if (!writer_->Write(tableName)) {
K
kun yu 已提交
403 404
            return SetError(SERVER_WRITE_ERROR, "Write table name failed!");
        }
K
kun yu 已提交
405 406 407 408 409
    }
    return SERVER_SUCCESS;
}

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
S
starlord 已提交
410 411 412 413 414 415
InsertTask::InsertTask(const ::milvus::grpc::InsertParam *insert_param,
                       ::milvus::grpc::VectorIds *record_ids)
    : GrpcBaseTask(DDL_DML_TASK_GROUP),
      insert_param_(insert_param),
      record_ids_(record_ids) {
    record_ids_->Clear();
K
kun yu 已提交
416 417
}

Y
Yu Kun 已提交
418
BaseTaskPtr
S
starlord 已提交
419 420 421 422 423 424
InsertTask::Create(const ::milvus::grpc::InsertParam *insert_param,
                         ::milvus::grpc::VectorIds *record_ids) {
    if(insert_param == nullptr) {
        SERVER_LOG_ERROR << "grpc input is null!";
        return nullptr;
    }
Y
Yu Kun 已提交
425
    return std::shared_ptr<GrpcBaseTask>(new InsertTask(insert_param, record_ids));
K
kun yu 已提交
426 427
}

Y
Yu Kun 已提交
428
ServerError
Y
Yu Kun 已提交
429
InsertTask::OnExecute() {
K
kun yu 已提交
430 431 432 433
    try {
        TimeRecorder rc("InsertVectorTask");

        //step 1: check arguments
S
starlord 已提交
434
        ServerError res = ValidationUtil::ValidateTableName(insert_param_->table_name());
Y
Yu Kun 已提交
435
        if (res != SERVER_SUCCESS) {
S
starlord 已提交
436
            return SetError(res, "Invalid table name: " + insert_param_->table_name());
K
kun yu 已提交
437
        }
S
starlord 已提交
438
        if (insert_param_->row_record_array().empty()) {
K
kun yu 已提交
439 440 441
            return SetError(SERVER_INVALID_ROWRECORD_ARRAY, "Row record array is empty");
        }

S
starlord 已提交
442 443
        if (!record_ids_->vector_id_array().empty()) {
            if (record_ids_->vector_id_array().size() != insert_param_->row_record_array_size()) {
Y
Yu Kun 已提交
444 445 446 447 448
                return SetError(SERVER_ILLEGAL_VECTOR_ID,
                        "Size of vector ids is not equal to row record array size");
            }
        }

K
kun yu 已提交
449 450
        //step 2: check table existence
        engine::meta::TableSchema table_info;
S
starlord 已提交
451
        table_info.table_id_ = insert_param_->table_name();
K
kun yu 已提交
452
        engine::Status stat = DBWrapper::DB()->DescribeTable(table_info);
Y
Yu Kun 已提交
453 454 455
        if (!stat.ok()) {
            if (stat.IsNotFound()) {
                return SetError(SERVER_TABLE_NOT_EXIST,
S
starlord 已提交
456
                                "Table " + insert_param_->table_name() + " not exists");
K
kun yu 已提交
457
            } else {
458
                return SetError(DB_META_TRANSACTION_FAILED, stat.ToString());
K
kun yu 已提交
459 460 461
            }
        }

462
        //step 3: check table flag
S
starlord 已提交
463
        //all user provide id, or all internal id
S
starlord 已提交
464
        bool user_provide_ids = !insert_param_->row_id_array().empty();
465 466 467 468
        //user already provided id before, all insert action require user id
        if((table_info.flag_ & engine::meta::FLAG_MASK_HAS_USERID) && !user_provide_ids) {
            return SetError(SERVER_INVALID_ARGUMENT, "Table vector ids are user defined, please provide id for this batch");
        }
S
starlord 已提交
469

470 471 472
        //user didn't provided id before, no need to provide user id
        if((table_info.flag_ & engine::meta::FLAG_MASK_NO_USERID) && user_provide_ids) {
            return SetError(SERVER_INVALID_ARGUMENT, "Table vector ids are auto generated, no need to provide id for this batch");
S
starlord 已提交
473 474
        }

K
kun yu 已提交
475 476 477
        rc.RecordSection("check validation");

#ifdef MILVUS_ENABLE_PROFILING
Y
Yu Kun 已提交
478
        std::string fname = "/tmp/insert_" + std::to_string(this->insert_param_->row_record_array_size()) + ".profiling";
K
kun yu 已提交
479 480
        ProfilerStart(fname.c_str());
#endif
K
kun yu 已提交
481

482
        //step 4: prepare float data
S
starlord 已提交
483
        std::vector<float> vec_f(insert_param_->row_record_array_size() * table_info.dimension_, 0);
K
kun yu 已提交
484

K
kun yu 已提交
485
        // TODO: change to one dimension array in protobuf or use multiple-thread to copy the data
S
starlord 已提交
486 487
        for (size_t i = 0; i < insert_param_->row_record_array_size(); i++) {
            if (insert_param_->row_record_array(i).vector_data().empty()) {
Y
Yu Kun 已提交
488 489
                return SetError(SERVER_INVALID_ROWRECORD_ARRAY, "Row record float array is empty");
            }
S
starlord 已提交
490
            uint64_t vec_dim = insert_param_->row_record_array(i).vector_data().size();
Y
Yu Kun 已提交
491 492 493 494 495 496
            if (vec_dim != table_info.dimension_) {
                ServerError error_code = SERVER_INVALID_VECTOR_DIMENSION;
                std::string error_msg = "Invalid rowrecord dimension: " + std::to_string(vec_dim)
                                        + " vs. table dimension:" +
                                        std::to_string(table_info.dimension_);
                return SetError(error_code, error_msg);
K
kun yu 已提交
497
            }
Y
yudong.cai 已提交
498
            memcpy(&vec_f[i * table_info.dimension_],
S
starlord 已提交
499
                   insert_param_->row_record_array(i).vector_data().data(),
Y
Yu Kun 已提交
500
                   table_info.dimension_ * sizeof(float));
K
kun yu 已提交
501 502
        }

K
kun yu 已提交
503
        rc.ElapseFromBegin("prepare vectors data");
K
kun yu 已提交
504

505
        //step 5: insert vectors
S
starlord 已提交
506 507 508 509
        auto vec_count = (uint64_t) insert_param_->row_record_array_size();
        std::vector<int64_t> vec_ids(insert_param_->row_id_array_size(), 0);
        if(!insert_param_->row_id_array().empty()) {
            const int64_t* src_data = insert_param_->row_id_array().data();
S
starlord 已提交
510
            int64_t* target_data = vec_ids.data();
S
starlord 已提交
511
            memcpy(target_data, src_data, (size_t)(sizeof(int64_t)*insert_param_->row_id_array_size()));
Y
Yu Kun 已提交
512
        }
K
kun yu 已提交
513

S
starlord 已提交
514
        stat = DBWrapper::DB()->InsertVectors(insert_param_->table_name(), vec_count, vec_f.data(), vec_ids);
K
kun yu 已提交
515
        rc.ElapseFromBegin("add vectors to engine");
Y
Yu Kun 已提交
516
        if (!stat.ok()) {
K
kun yu 已提交
517 518
            return SetError(SERVER_CACHE_ERROR, "Cache error: " + stat.ToString());
        }
K
kun yu 已提交
519
        for (int64_t id : vec_ids) {
S
starlord 已提交
520
            record_ids_->add_vector_id_array(id);
K
kun yu 已提交
521 522
        }

S
starlord 已提交
523
        auto ids_size = record_ids_->vector_id_array_size();
Y
Yu Kun 已提交
524
        if (ids_size != vec_count) {
K
kun yu 已提交
525
            std::string msg = "Add " + std::to_string(vec_count) + " vectors but only return "
K
kun yu 已提交
526
                              + std::to_string(ids_size) + " id";
K
kun yu 已提交
527 528 529
            return SetError(SERVER_ILLEGAL_VECTOR_ID, msg);
        }

530 531 532 533
        //step 6: update table flag
        user_provide_ids ? table_info.flag_ |= engine::meta::FLAG_MASK_HAS_USERID
                : table_info.flag_ |= engine::meta::FLAG_MASK_NO_USERID;
        stat = DBWrapper::DB()->UpdateTableFlag(insert_param_->table_name(), table_info.flag_);
S
starlord 已提交
534

K
kun yu 已提交
535 536 537 538 539 540
#ifdef MILVUS_ENABLE_PROFILING
        ProfilerStop();
#endif

        rc.RecordSection("add vectors to engine");
        rc.ElapseFromBegin("total cost");
K
kun yu 已提交
541

Y
Yu Kun 已提交
542
    } catch (std::exception &ex) {
K
kun yu 已提交
543 544 545 546 547 548 549
        return SetError(SERVER_UNEXPECTED_ERROR, ex.what());
    }

    return SERVER_SUCCESS;
}

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
S
starlord 已提交
550
SearchTask::SearchTask(const ::milvus::grpc::SearchParam *search_vector_infos,
551 552 553 554 555 556
                       const std::vector<std::string> &file_id_array,
                       ::milvus::grpc::TopKQueryResultList *response)
    : GrpcBaseTask(DQL_TASK_GROUP),
      search_param_(search_vector_infos),
      file_id_array_(file_id_array),
      topk_result_list(response) {
K
kun yu 已提交
557 558 559

}

Y
Yu Kun 已提交
560
BaseTaskPtr
S
starlord 已提交
561 562
SearchTask::Create(const ::milvus::grpc::SearchParam *search_vector_infos,
                   const std::vector<std::string> &file_id_array,
563
                   ::milvus::grpc::TopKQueryResultList *response) {
S
starlord 已提交
564 565 566 567
    if(search_vector_infos == nullptr) {
        SERVER_LOG_ERROR << "grpc input is null!";
        return nullptr;
    }
Y
Yu Kun 已提交
568
    return std::shared_ptr<GrpcBaseTask>(new SearchTask(search_vector_infos, file_id_array,
569
                                                        response));
K
kun yu 已提交
570 571
}

Y
Yu Kun 已提交
572
ServerError
Y
Yu Kun 已提交
573
SearchTask::OnExecute() {
K
kun yu 已提交
574
    try {
Y
Yu Kun 已提交
575
        TimeRecorder rc("SearchTask");
K
kun yu 已提交
576

577
        //step 1: check table name
S
starlord 已提交
578
        std::string table_name_ = search_param_->table_name();
K
kun yu 已提交
579
        ServerError res = ValidationUtil::ValidateTableName(table_name_);
Y
Yu Kun 已提交
580
        if (res != SERVER_SUCCESS) {
K
kun yu 已提交
581 582 583 584 585 586 587
            return SetError(res, "Invalid table name: " + table_name_);
        }

        //step 2: check table existence
        engine::meta::TableSchema table_info;
        table_info.table_id_ = table_name_;
        engine::Status stat = DBWrapper::DB()->DescribeTable(table_info);
Y
Yu Kun 已提交
588 589
        if (!stat.ok()) {
            if (stat.IsNotFound()) {
K
kun yu 已提交
590 591
                return SetError(SERVER_TABLE_NOT_EXIST, "Table " + table_name_ + " not exists");
            } else {
592
                return SetError(DB_META_TRANSACTION_FAILED, stat.ToString());
K
kun yu 已提交
593 594 595
            }
        }

596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613
        //step 3: check search parameter
        int64_t top_k = search_param_->topk();
        res = ValidationUtil::ValidateSearchTopk(top_k, table_info);
        if (res != SERVER_SUCCESS) {
            return SetError(res, "Invalid topk: " + std::to_string(top_k));
        }

        int64_t nprobe = search_param_->nprobe();
        res = ValidationUtil::ValidateSearchNprobe(nprobe, table_info);
        if (res != SERVER_SUCCESS) {
            return SetError(res, "Invalid nprobe: " + std::to_string(nprobe));
        }

        if (search_param_->query_record_array().empty()) {
            return SetError(SERVER_INVALID_ROWRECORD_ARRAY, "Row record array is empty");
        }

        //step 4: check date range, and convert to db dates
K
kun yu 已提交
614 615 616 617 618
        std::vector<DB_DATE> dates;
        ServerError error_code = SERVER_SUCCESS;
        std::string error_msg;

        std::vector<::milvus::grpc::Range> range_array;
S
starlord 已提交
619 620
        for (size_t i = 0; i < search_param_->query_range_array_size(); i++) {
            range_array.emplace_back(search_param_->query_range_array(i));
K
kun yu 已提交
621 622
        }
        ConvertTimeRangeToDBDates(range_array, dates, error_code, error_msg);
Y
Yu Kun 已提交
623
        if (error_code != SERVER_SUCCESS) {
K
kun yu 已提交
624 625 626
            return SetError(error_code, error_msg);
        }

K
kun yu 已提交
627 628
        double span_check = rc.RecordSection("check validation");

K
kun yu 已提交
629

630
        //step 5: prepare float data
S
starlord 已提交
631
        auto record_array_size = search_param_->query_record_array_size();
K
kun yu 已提交
632 633
        std::vector<float> vec_f(record_array_size * table_info.dimension_, 0);
        for (size_t i = 0; i < record_array_size; i++) {
S
starlord 已提交
634
            if (search_param_->query_record_array(i).vector_data().empty()) {
635
                return SetError(SERVER_INVALID_ROWRECORD_ARRAY, "Query record float array is empty");
K
kun yu 已提交
636
            }
S
starlord 已提交
637
            uint64_t query_vec_dim = search_param_->query_record_array(i).vector_data().size();
638 639 640 641 642 643 644 645
            if (query_vec_dim != table_info.dimension_) {
                ServerError error_code = SERVER_INVALID_VECTOR_DIMENSION;
                std::string error_msg = "Invalid rowrecord dimension: " + std::to_string(query_vec_dim)
                                        + " vs. table dimension:" + std::to_string(table_info.dimension_);
                return SetError(error_code, error_msg);
            }

            memcpy(&vec_f[i * table_info.dimension_],
S
starlord 已提交
646
                   search_param_->query_record_array(i).vector_data().data(),
647
                   table_info.dimension_ * sizeof(float));
K
kun yu 已提交
648
        }
K
kun yu 已提交
649
        rc.ElapseFromBegin("prepare vector data");
K
kun yu 已提交
650

651
        //step 6: search vectors
K
kun yu 已提交
652
        engine::QueryResults results;
S
starlord 已提交
653
        auto record_count = (uint64_t) search_param_->query_record_array().size();
K
kun yu 已提交
654

Y
Yu Kun 已提交
655 656 657 658 659
#ifdef MILVUS_ENABLE_PROFILING
        std::string fname = "/tmp/search_nq_" + std::to_string(this->search_param_->query_record_array_size()) + ".profiling";
        ProfilerStart(fname.c_str());
#endif

Y
Yu Kun 已提交
660
        if (file_id_array_.empty()) {
661
            stat = DBWrapper::DB()->Query(table_name_, (size_t) top_k, record_count, nprobe, vec_f.data(),
Y
Yu Kun 已提交
662
                                          dates, results);
K
kun yu 已提交
663
        } else {
664
            stat = DBWrapper::DB()->Query(table_name_, file_id_array_, (size_t) top_k,
Y
Yu Kun 已提交
665
                                          record_count, nprobe, vec_f.data(), dates, results);
K
kun yu 已提交
666 667
        }

Y
Yu Kun 已提交
668 669 670 671
#ifdef MILVUS_ENABLE_PROFILING
        ProfilerStop();
#endif

K
kun yu 已提交
672
        rc.ElapseFromBegin("search vectors from engine");
Y
Yu Kun 已提交
673
        if (!stat.ok()) {
674
            return SetError(DB_META_TRANSACTION_FAILED, stat.ToString());
K
kun yu 已提交
675 676
        }

Y
Yu Kun 已提交
677
        if (results.empty()) {
K
kun yu 已提交
678 679 680
            return SERVER_SUCCESS; //empty table
        }

Y
Yu Kun 已提交
681
        if (results.size() != record_count) {
K
kun yu 已提交
682 683 684 685 686
            std::string msg = "Search " + std::to_string(record_count) + " vectors but only return "
                              + std::to_string(results.size()) + " results";
            return SetError(SERVER_ILLEGAL_SEARCH_RESULT, msg);
        }

K
kun yu 已提交
687
        rc.ElapseFromBegin("do search");
K
kun yu 已提交
688

689
        //step 7: construct result array
690 691
        for (auto &result : results) {
            ::milvus::grpc::TopKQueryResult *topk_query_result = topk_result_list->add_topk_query_result();
Y
Yu Kun 已提交
692
            for (auto &pair : result) {
693
                ::milvus::grpc::QueryResult *grpc_result = topk_query_result->add_query_result_arrays();
K
kun yu 已提交
694 695 696 697
                grpc_result->set_id(pair.first);
                grpc_result->set_distance(pair.second);
            }
        }
K
kun yu 已提交
698

699
        //step 8: print time cost percent
K
kun yu 已提交
700 701 702
        double span_result = rc.RecordSection("construct result");
        rc.ElapseFromBegin("totally cost");

K
kun yu 已提交
703

Y
Yu Kun 已提交
704
    } catch (std::exception &ex) {
K
kun yu 已提交
705 706 707 708 709 710 711
        return SetError(SERVER_UNEXPECTED_ERROR, ex.what());
    }

    return SERVER_SUCCESS;
}

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
Y
Yu Kun 已提交
712
CountTableTask::CountTableTask(const std::string &table_name, int64_t &row_count)
Y
Yu Kun 已提交
713
        : GrpcBaseTask(DDL_DML_TASK_GROUP),
K
kun yu 已提交
714 715 716 717 718
          table_name_(table_name),
          row_count_(row_count) {

}

Y
Yu Kun 已提交
719
BaseTaskPtr
Y
Yu Kun 已提交
720 721
CountTableTask::Create(const std::string &table_name, int64_t &row_count) {
    return std::shared_ptr<GrpcBaseTask>(new CountTableTask(table_name, row_count));
K
kun yu 已提交
722 723
}

Y
Yu Kun 已提交
724
ServerError
Y
Yu Kun 已提交
725
CountTableTask::OnExecute() {
K
kun yu 已提交
726 727 728 729 730
    try {
        TimeRecorder rc("GetTableRowCountTask");

        //step 1: check arguments
        ServerError res = SERVER_SUCCESS;
K
kun yu 已提交
731
        res = ValidationUtil::ValidateTableName(table_name_);
Y
Yu Kun 已提交
732
        if (res != SERVER_SUCCESS) {
K
kun yu 已提交
733 734 735 736 737 738 739
            return SetError(res, "Invalid table name: " + table_name_);
        }

        //step 2: get row count
        uint64_t row_count = 0;
        engine::Status stat = DBWrapper::DB()->GetTableRowCount(table_name_, row_count);
        if (!stat.ok()) {
740
            return SetError(DB_META_TRANSACTION_FAILED, stat.ToString());
K
kun yu 已提交
741 742 743 744
        }

        row_count_ = (int64_t) row_count;

K
kun yu 已提交
745
        rc.ElapseFromBegin("total cost");
K
kun yu 已提交
746

Y
Yu Kun 已提交
747
    } catch (std::exception &ex) {
K
kun yu 已提交
748 749 750 751 752 753 754
        return SetError(SERVER_UNEXPECTED_ERROR, ex.what());
    }

    return SERVER_SUCCESS;
}

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
Y
Yu Kun 已提交
755
CmdTask::CmdTask(const std::string &cmd, std::string &result)
Y
Yu Kun 已提交
756
        : GrpcBaseTask(PING_TASK_GROUP),
K
kun yu 已提交
757 758 759 760 761
          cmd_(cmd),
          result_(result) {

}

Y
Yu Kun 已提交
762
BaseTaskPtr
Y
Yu Kun 已提交
763 764
CmdTask::Create(const std::string &cmd, std::string &result) {
    return std::shared_ptr<GrpcBaseTask>(new CmdTask(cmd, result));
K
kun yu 已提交
765 766
}

Y
Yu Kun 已提交
767
ServerError
Y
Yu Kun 已提交
768
CmdTask::OnExecute() {
Y
Yu Kun 已提交
769
    if (cmd_ == "version") {
K
kun yu 已提交
770
        result_ = MILVUS_VERSION;
771 772 773 774
    } else if (cmd_ == "tasktable") {
        result_ = engine::ResMgrInst::GetInstance()->DumpTaskTables();
    }
    else {
K
kun yu 已提交
775
        result_ = "OK";
K
kun yu 已提交
776 777 778 779 780
    }

    return SERVER_SUCCESS;
}

781
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
S
starlord 已提交
782
DeleteByRangeTask::DeleteByRangeTask(const ::milvus::grpc::DeleteByRangeParam *delete_by_range_param)
783 784 785 786 787
        : GrpcBaseTask(DDL_DML_TASK_GROUP),
          delete_by_range_param_(delete_by_range_param){
}

BaseTaskPtr
S
starlord 已提交
788 789 790 791 792
DeleteByRangeTask::Create(const ::milvus::grpc::DeleteByRangeParam *delete_by_range_param) {
    if(delete_by_range_param == nullptr) {
        SERVER_LOG_ERROR << "grpc input is null!";
        return nullptr;
    }
793 794 795 796 797 798 799 800 801
    return std::shared_ptr<GrpcBaseTask>(new DeleteByRangeTask(delete_by_range_param));
}

ServerError
DeleteByRangeTask::OnExecute() {
    try {
        TimeRecorder rc("DeleteByRangeTask");

        //step 1: check arguments
S
starlord 已提交
802
        std::string table_name = delete_by_range_param_->table_name();
803 804 805 806 807 808 809 810 811 812 813 814 815
        ServerError res = ValidationUtil::ValidateTableName(table_name);
        if (res != SERVER_SUCCESS) {
            return SetError(res, "Invalid table name: " + table_name);
        }

        //step 2: check table existence
        engine::meta::TableSchema table_info;
        table_info.table_id_ = table_name;
        engine::Status stat = DBWrapper::DB()->DescribeTable(table_info);
        if (!stat.ok()) {
            if (stat.IsNotFound()) {
                return SetError(SERVER_TABLE_NOT_EXIST, "Table " + table_name + " not exists");
            } else {
816
                return SetError(DB_META_TRANSACTION_FAILED, stat.ToString());
817 818 819 820 821 822 823 824 825 826 827
            }
        }

        rc.ElapseFromBegin("check validation");

        //step 3: check date range, and convert to db dates
        std::vector<DB_DATE> dates;
        ServerError error_code = SERVER_SUCCESS;
        std::string error_msg;

        std::vector<::milvus::grpc::Range> range_array;
S
starlord 已提交
828
        range_array.emplace_back(delete_by_range_param_->range());
829 830 831 832 833 834
        ConvertTimeRangeToDBDates(range_array, dates, error_code, error_msg);
        if (error_code != SERVER_SUCCESS) {
            return SetError(error_code, error_msg);
        }

#ifdef MILVUS_ENABLE_PROFILING
Y
Yu Kun 已提交
835
        std::string fname = "/tmp/search_nq_" + this->delete_by_range_param_->table_name() + ".profiling";
836 837 838 839
        ProfilerStart(fname.c_str());
#endif
        engine::Status status = DBWrapper::DB()->DeleteTable(table_name, dates);
        if (!status.ok()) {
840
            return SetError(DB_META_TRANSACTION_FAILED, stat.ToString());
841 842 843 844 845 846 847 848 849
        }

    } catch (std::exception &ex) {
        return SetError(SERVER_UNEXPECTED_ERROR, ex.what());
    }
    
    return SERVER_SUCCESS;
}

Y
Yu Kun 已提交
850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
PreloadTableTask::PreloadTableTask(const std::string &table_name)
        : GrpcBaseTask(DDL_DML_TASK_GROUP),
          table_name_(table_name) {

}

BaseTaskPtr
PreloadTableTask::Create(const std::string &table_name){
    return std::shared_ptr<GrpcBaseTask>(new PreloadTableTask(table_name));
}

ServerError
PreloadTableTask::OnExecute() {
    try {
        TimeRecorder rc("PreloadTableTask");

        //step 1: check arguments
        ServerError res = ValidationUtil::ValidateTableName(table_name_);
        if (res != SERVER_SUCCESS) {
            return SetError(res, "Invalid table name: " + table_name_);
        }

        //step 2: check table existence
        engine::Status stat = DBWrapper::DB()->PreloadTable(table_name_);
        if (!stat.ok()) {
876
            return SetError(DB_META_TRANSACTION_FAILED, stat.ToString());
Y
Yu Kun 已提交
877 878 879 880 881 882 883 884 885 886
        }

        rc.ElapseFromBegin("totally cost");
    } catch (std::exception &ex) {
        return SetError(SERVER_UNEXPECTED_ERROR, ex.what());
    }

    return SERVER_SUCCESS;
}

887 888
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
DescribeIndexTask::DescribeIndexTask(const std::string &table_name,
S
starlord 已提交
889
                                     ::milvus::grpc::IndexParam *index_param)
890 891 892 893 894 895 896 897
    : GrpcBaseTask(DDL_DML_TASK_GROUP),
      table_name_(table_name),
      index_param_(index_param) {

}

BaseTaskPtr
DescribeIndexTask::Create(const std::string &table_name,
S
starlord 已提交
898
                          ::milvus::grpc::IndexParam *index_param){
899 900 901 902 903 904 905
    return std::shared_ptr<GrpcBaseTask>(new DescribeIndexTask(table_name, index_param));
}

ServerError
DescribeIndexTask::OnExecute() {
    try {
        TimeRecorder rc("DescribeIndexTask");
Y
Yu Kun 已提交
906

907 908 909 910 911 912 913 914 915 916
        //step 1: check arguments
        ServerError res = ValidationUtil::ValidateTableName(table_name_);
        if (res != SERVER_SUCCESS) {
            return SetError(res, "Invalid table name: " + table_name_);
        }

        //step 2: check table existence
        engine::TableIndex index;
        engine::Status stat = DBWrapper::DB()->DescribeIndex(table_name_, index);
        if (!stat.ok()) {
917
            return SetError(DB_META_TRANSACTION_FAILED, stat.ToString());
918 919
        }

S
starlord 已提交
920 921 922
        index_param_->mutable_table_name()->set_table_name(table_name_);
        index_param_->mutable_index()->set_index_type(index.engine_type_);
        index_param_->mutable_index()->set_nlist(index.nlist_);
923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954

        rc.ElapseFromBegin("totally cost");
    } catch (std::exception &ex) {
        return SetError(SERVER_UNEXPECTED_ERROR, ex.what());
    }

    return SERVER_SUCCESS;
}

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
DropIndexTask::DropIndexTask(const std::string &table_name)
    : GrpcBaseTask(DDL_DML_TASK_GROUP),
      table_name_(table_name) {

}

BaseTaskPtr
DropIndexTask::Create(const std::string &table_name){
    return std::shared_ptr<GrpcBaseTask>(new DropIndexTask(table_name));
}

ServerError
DropIndexTask::OnExecute() {
    try {
        TimeRecorder rc("DropIndexTask");

        //step 1: check arguments
        ServerError res = ValidationUtil::ValidateTableName(table_name_);
        if (res != SERVER_SUCCESS) {
            return SetError(res, "Invalid table name: " + table_name_);
        }

955 956
        //step 2: check table existence
        auto stat = DBWrapper::DB()->DropIndex(table_name_);
957
        if (!stat.ok()) {
958
            return SetError(DB_META_TRANSACTION_FAILED, stat.ToString());
959 960 961 962 963 964 965 966 967
        }

        rc.ElapseFromBegin("totally cost");
    } catch (std::exception &ex) {
        return SetError(SERVER_UNEXPECTED_ERROR, ex.what());
    }

    return SERVER_SUCCESS;
}
Y
Yu Kun 已提交
968

Y
Yu Kun 已提交
969
}
K
kun yu 已提交
970 971 972
}
}
}