ValidationUtil.cpp 19.9 KB
Newer Older
1
// Copyright (C) 2019-2020 Zilliz. All rights reserved.
J
jinhai 已提交
2
//
3 4
// 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
J
jinhai 已提交
5
//
6 7 8 9 10
// 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.
J
jinhai 已提交
11

S
starlord 已提交
12
#include "utils/ValidationUtil.h"
J
jinhai 已提交
13
#include "Log.h"
14
#include "db/Utils.h"
S
starlord 已提交
15
#include "db/engine/ExecutionEngine.h"
16
#include "index/knowhere/knowhere/index/vector_index/helpers/IndexParameter.h"
17
#include "utils/StringHelpFunctions.h"
J
jinhai 已提交
18

Z
zhiru 已提交
19
#include <arpa/inet.h>
G
groot 已提交
20

Y
youny626 已提交
21
#ifdef MILVUS_GPU_VERSION
G
groot 已提交
22

S
starlord 已提交
23
#include <cuda_runtime.h>
G
groot 已提交
24

Y
youny626 已提交
25
#endif
G
groot 已提交
26

S
shengjh 已提交
27
#include <fiu-local.h>
28
#include <src/db/Types.h>
Z
zhiru 已提交
29
#include <algorithm>
J
JinHai-CN 已提交
30
#include <cmath>
S
starlord 已提交
31 32
#include <regex>
#include <string>
Z
zhiru 已提交
33

J
jinhai 已提交
34 35 36
namespace milvus {
namespace server {

37
namespace {
38
constexpr size_t TABLE_NAME_SIZE_LIMIT = 255;
G
groot 已提交
39
constexpr int64_t TABLE_DIMENSION_LIMIT = 32768;
S
starlord 已提交
40
constexpr int32_t INDEX_FILE_SIZE_LIMIT = 4096;  // index trigger size max = 4096 MB
J
jinhai 已提交
41

42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92
Status
CheckParameterRange(const milvus::json& json_params, const std::string& param_name, int64_t min, int64_t max,
                    bool min_close = true, bool max_closed = true) {
    if (json_params.find(param_name) == json_params.end()) {
        std::string msg = "Parameter list must contain: ";
        return Status(SERVER_INVALID_ARGUMENT, msg + param_name);
    }

    try {
        int64_t value = json_params[param_name];
        bool min_err = min_close ? value < min : value <= min;
        bool max_err = max_closed ? value > max : value >= max;
        if (min_err || max_err) {
            std::string msg = "Invalid " + param_name + " value: " + std::to_string(value) + ". Valid range is " +
                              (min_close ? "[" : "(") + std::to_string(min) + ", " + std::to_string(max) +
                              (max_closed ? "]" : ")");
            SERVER_LOG_ERROR << msg;
            return Status(SERVER_INVALID_ARGUMENT, msg);
        }
    } catch (std::exception& e) {
        std::string msg = "Invalid " + param_name + ": ";
        return Status(SERVER_INVALID_ARGUMENT, msg + e.what());
    }

    return Status::OK();
}

Status
CheckParameterExistence(const milvus::json& json_params, const std::string& param_name) {
    if (json_params.find(param_name) == json_params.end()) {
        std::string msg = "Parameter list must contain: ";
        return Status(SERVER_INVALID_ARGUMENT, msg + param_name);
    }

    try {
        int64_t value = json_params[param_name];
        if (value < 0) {
            std::string msg = "Invalid " + param_name + " value: " + std::to_string(value);
            SERVER_LOG_ERROR << msg;
            return Status(SERVER_INVALID_ARGUMENT, msg);
        }
    } catch (std::exception& e) {
        std::string msg = "Invalid " + param_name + ": ";
        return Status(SERVER_INVALID_ARGUMENT, msg + e.what());
    }

    return Status::OK();
}

}  // namespace

S
starlord 已提交
93
Status
S
starlord 已提交
94
ValidationUtil::ValidateTableName(const std::string& table_name) {
J
jinhai 已提交
95 96
    // Table name shouldn't be empty.
    if (table_name.empty()) {
97
        std::string msg = "Table name should not be empty.";
S
starlord 已提交
98 99
        SERVER_LOG_ERROR << msg;
        return Status(SERVER_INVALID_TABLE_NAME, msg);
J
jinhai 已提交
100 101
    }

102
    std::string invalid_msg = "Invalid table name: " + table_name + ". ";
J
jinhai 已提交
103
    // Table name size shouldn't exceed 16384.
104
    if (table_name.size() > TABLE_NAME_SIZE_LIMIT) {
105
        std::string msg = invalid_msg + "The length of a table name must be less than 255 characters.";
S
starlord 已提交
106 107
        SERVER_LOG_ERROR << msg;
        return Status(SERVER_INVALID_TABLE_NAME, msg);
J
jinhai 已提交
108 109 110 111 112
    }

    // Table name first character should be underscore or character.
    char first_char = table_name[0];
    if (first_char != '_' && std::isalpha(first_char) == 0) {
113
        std::string msg = invalid_msg + "The first character of a table name must be an underscore or letter.";
S
starlord 已提交
114 115
        SERVER_LOG_ERROR << msg;
        return Status(SERVER_INVALID_TABLE_NAME, msg);
J
jinhai 已提交
116 117 118 119 120 121
    }

    int64_t table_name_size = table_name.size();
    for (int64_t i = 1; i < table_name_size; ++i) {
        char name_char = table_name[i];
        if (name_char != '_' && std::isalnum(name_char) == 0) {
122
            std::string msg = invalid_msg + "Table name can only contain numbers, letters, and underscores.";
S
starlord 已提交
123 124
            SERVER_LOG_ERROR << msg;
            return Status(SERVER_INVALID_TABLE_NAME, msg);
J
jinhai 已提交
125 126 127
        }
    }

S
starlord 已提交
128
    return Status::OK();
J
jinhai 已提交
129 130
}

S
starlord 已提交
131
Status
132
ValidationUtil::ValidateTableDimension(int64_t dimension, int64_t metric_type) {
133
    if (dimension <= 0 || dimension > TABLE_DIMENSION_LIMIT) {
S
starlord 已提交
134
        std::string msg = "Invalid table dimension: " + std::to_string(dimension) + ". " +
G
groot 已提交
135 136
                          "The table dimension must be within the range of 1 ~ " +
                          std::to_string(TABLE_DIMENSION_LIMIT) + ".";
S
starlord 已提交
137 138
        SERVER_LOG_ERROR << msg;
        return Status(SERVER_INVALID_VECTOR_DIMENSION, msg);
J
jinhai 已提交
139
    }
140 141 142 143 144 145 146 147 148 149 150

    if (milvus::engine::utils::IsBinaryMetricType(metric_type)) {
        if ((dimension % 8) != 0) {
            std::string msg = "Invalid table dimension: " + std::to_string(dimension) + ". " +
                              "The table dimension must be a multiple of 8";
            SERVER_LOG_ERROR << msg;
            return Status(SERVER_INVALID_VECTOR_DIMENSION, msg);
        }
    }

    return Status::OK();
J
jinhai 已提交
151 152
}

S
starlord 已提交
153
Status
154
ValidationUtil::ValidateTableIndexType(int32_t index_type) {
S
starlord 已提交
155 156
    int engine_type = static_cast<int>(engine::EngineType(index_type));
    if (engine_type <= 0 || engine_type > static_cast<int>(engine::EngineType::MAX_VALUE)) {
S
starlord 已提交
157 158
        std::string msg = "Invalid index type: " + std::to_string(index_type) + ". " +
                          "Make sure the index type is in IndexType list.";
S
starlord 已提交
159 160
        SERVER_LOG_ERROR << msg;
        return Status(SERVER_INVALID_INDEX_TYPE, msg);
J
jinhai 已提交
161
    }
162

163 164 165 166 167 168 169 170 171
#ifndef CUSTOMIZATION
    // special case, hybird index only available in customize faiss library
    if (engine_type == static_cast<int>(engine::EngineType::FAISS_IVFSQ8H)) {
        std::string msg = "Unsupported index type: " + std::to_string(index_type);
        SERVER_LOG_ERROR << msg;
        return Status(SERVER_INVALID_INDEX_TYPE, msg);
    }
#endif

S
starlord 已提交
172
    return Status::OK();
J
jinhai 已提交
173 174
}

175 176 177 178 179 180 181 182 183 184 185 186
Status
ValidationUtil::ValidateIndexParams(const milvus::json& index_params, const engine::meta::TableSchema& table_schema,
                                    int32_t index_type) {
    switch (index_type) {
        case (int32_t)engine::EngineType::FAISS_IDMAP:
        case (int32_t)engine::EngineType::FAISS_BIN_IDMAP: {
            break;
        }
        case (int32_t)engine::EngineType::FAISS_IVFFLAT:
        case (int32_t)engine::EngineType::FAISS_IVFSQ8:
        case (int32_t)engine::EngineType::FAISS_IVFSQ8H:
        case (int32_t)engine::EngineType::FAISS_BIN_IVFFLAT: {
G
typo  
groot 已提交
187
            auto status = CheckParameterRange(index_params, knowhere::IndexParams::nlist, 1, 999999);
188 189 190 191 192 193
            if (!status.ok()) {
                return status;
            }
            break;
        }
        case (int32_t)engine::EngineType::FAISS_PQ: {
G
typo  
groot 已提交
194
            auto status = CheckParameterRange(index_params, knowhere::IndexParams::nlist, 1, 999999);
195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237
            if (!status.ok()) {
                return status;
            }

            status = CheckParameterExistence(index_params, knowhere::IndexParams::m);
            if (!status.ok()) {
                return status;
            }

            break;
        }
        case (int32_t)engine::EngineType::NSG_MIX: {
            auto status = CheckParameterRange(index_params, knowhere::IndexParams::search_length, 10, 300);
            if (!status.ok()) {
                return status;
            }
            status = CheckParameterRange(index_params, knowhere::IndexParams::out_degree, 5, 300);
            if (!status.ok()) {
                return status;
            }
            status = CheckParameterRange(index_params, knowhere::IndexParams::candidate, 50, 1000);
            if (!status.ok()) {
                return status;
            }
            status = CheckParameterRange(index_params, knowhere::IndexParams::knng, 5, 300);
            if (!status.ok()) {
                return status;
            }
            break;
        }
        case (int32_t)engine::EngineType::HNSW: {
            auto status = CheckParameterRange(index_params, knowhere::IndexParams::M, 5, 48);
            if (!status.ok()) {
                return status;
            }
            status = CheckParameterRange(index_params, knowhere::IndexParams::efConstruction, 100, 500);
            if (!status.ok()) {
                return status;
            }
            break;
        }
    }
    return Status::OK();
G
groot 已提交
238 239
}

S
starlord 已提交
240
Status
241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266
ValidationUtil::ValidateSearchParams(const milvus::json& search_params, const engine::meta::TableSchema& table_schema,
                                     int64_t topk) {
    switch (table_schema.engine_type_) {
        case (int32_t)engine::EngineType::FAISS_IDMAP:
        case (int32_t)engine::EngineType::FAISS_BIN_IDMAP: {
            break;
        }
        case (int32_t)engine::EngineType::FAISS_IVFFLAT:
        case (int32_t)engine::EngineType::FAISS_IVFSQ8:
        case (int32_t)engine::EngineType::FAISS_IVFSQ8H:
        case (int32_t)engine::EngineType::FAISS_BIN_IVFFLAT:
        case (int32_t)engine::EngineType::FAISS_PQ: {
            auto status = CheckParameterRange(search_params, knowhere::IndexParams::nprobe, 1, 999999);
            if (!status.ok()) {
                return status;
            }
            break;
        }
        case (int32_t)engine::EngineType::NSG_MIX: {
            auto status = CheckParameterRange(search_params, knowhere::IndexParams::search_length, 10, 300);
            if (!status.ok()) {
                return status;
            }
            break;
        }
        case (int32_t)engine::EngineType::HNSW: {
G
typo  
groot 已提交
267
            auto status = CheckParameterRange(search_params, knowhere::IndexParams::ef, topk, 4096);
268 269 270 271 272
            if (!status.ok()) {
                return status;
            }
            break;
        }
S
starlord 已提交
273
    }
S
starlord 已提交
274
    return Status::OK();
S
starlord 已提交
275 276
}

S
starlord 已提交
277
Status
278
ValidationUtil::ValidateTableIndexFileSize(int64_t index_file_size) {
Z
zhiru 已提交
279
    if (index_file_size <= 0 || index_file_size > INDEX_FILE_SIZE_LIMIT) {
S
starlord 已提交
280 281 282
        std::string msg = "Invalid index file size: " + std::to_string(index_file_size) + ". " +
                          "The index file size must be within the range of 1 ~ " +
                          std::to_string(INDEX_FILE_SIZE_LIMIT) + ".";
S
starlord 已提交
283 284
        SERVER_LOG_ERROR << msg;
        return Status(SERVER_INVALID_INDEX_FILE_SIZE, msg);
S
starlord 已提交
285 286
    }

S
starlord 已提交
287
    return Status::OK();
S
starlord 已提交
288 289
}

S
starlord 已提交
290
Status
S
starlord 已提交
291
ValidationUtil::ValidateTableIndexMetricType(int32_t metric_type) {
G
groot 已提交
292
    if (metric_type <= 0 || metric_type > static_cast<int32_t>(engine::MetricType::MAX_VALUE)) {
S
starlord 已提交
293
        std::string msg = "Invalid index metric type: " + std::to_string(metric_type) + ". " +
G
groot 已提交
294
                          "Make sure the metric type is in MetricType list.";
S
starlord 已提交
295 296
        SERVER_LOG_ERROR << msg;
        return Status(SERVER_INVALID_INDEX_METRIC_TYPE, msg);
S
starlord 已提交
297
    }
S
starlord 已提交
298
    return Status::OK();
S
starlord 已提交
299 300
}

S
starlord 已提交
301
Status
S
starlord 已提交
302
ValidationUtil::ValidateSearchTopk(int64_t top_k, const engine::meta::TableSchema& table_schema) {
303
    if (top_k <= 0 || top_k > 2048) {
S
starlord 已提交
304 305
        std::string msg =
            "Invalid topk: " + std::to_string(top_k) + ". " + "The topk must be within the range of 1 ~ 2048.";
S
starlord 已提交
306 307
        SERVER_LOG_ERROR << msg;
        return Status(SERVER_INVALID_TOPK, msg);
308 309
    }

S
starlord 已提交
310
    return Status::OK();
311 312
}

313 314 315 316 317 318 319 320
Status
ValidationUtil::ValidatePartitionName(const std::string& partition_name) {
    if (partition_name.empty()) {
        std::string msg = "Partition name should not be empty.";
        SERVER_LOG_ERROR << msg;
        return Status(SERVER_INVALID_TABLE_NAME, msg);
    }

321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347
    std::string invalid_msg = "Invalid partition name: " + partition_name + ". ";
    // Table name size shouldn't exceed 16384.
    if (partition_name.size() > TABLE_NAME_SIZE_LIMIT) {
        std::string msg = invalid_msg + "The length of a partition name must be less than 255 characters.";
        SERVER_LOG_ERROR << msg;
        return Status(SERVER_INVALID_TABLE_NAME, msg);
    }

    // Table name first character should be underscore or character.
    char first_char = partition_name[0];
    if (first_char != '_' && std::isalpha(first_char) == 0) {
        std::string msg = invalid_msg + "The first character of a partition name must be an underscore or letter.";
        SERVER_LOG_ERROR << msg;
        return Status(SERVER_INVALID_TABLE_NAME, msg);
    }

    int64_t table_name_size = partition_name.size();
    for (int64_t i = 1; i < table_name_size; ++i) {
        char name_char = partition_name[i];
        if (name_char != '_' && std::isalnum(name_char) == 0) {
            std::string msg = invalid_msg + "Partition name can only contain numbers, letters, and underscores.";
            SERVER_LOG_ERROR << msg;
            return Status(SERVER_INVALID_TABLE_NAME, msg);
        }
    }

    return Status::OK();
348 349
}

G
groot 已提交
350 351
Status
ValidationUtil::ValidatePartitionTags(const std::vector<std::string>& partition_tags) {
352 353 354 355 356 357 358
    for (const std::string& tag : partition_tags) {
        // trim side-blank of tag, only compare valid characters
        // for example: " ab cd " is treated as "ab cd"
        std::string valid_tag = tag;
        StringHelpFunctions::TrimStringBlank(valid_tag);
        if (valid_tag.empty()) {
            std::string msg = "Invalid partition tag: " + valid_tag + ". " + "Partition tag should not be empty.";
G
groot 已提交
359
            SERVER_LOG_ERROR << msg;
360
            return Status(SERVER_INVALID_TABLE_NAME, msg);
G
groot 已提交
361
        }
362 363 364 365 366 367 368

        // max length of partition tag
        if (valid_tag.length() > 255) {
            std::string msg = "Invalid partition tag: " + valid_tag + ". " + "Partition tag exceed max length(255).";
            SERVER_LOG_ERROR << msg;
            return Status(SERVER_INVALID_PARTITION_TAG, msg);
        }
G
groot 已提交
369 370 371 372 373
    }

    return Status::OK();
}

S
starlord 已提交
374
Status
375
ValidationUtil::ValidateGpuIndex(int32_t gpu_index) {
Y
youny626 已提交
376
#ifdef MILVUS_GPU_VERSION
377 378
    int num_devices = 0;
    auto cuda_err = cudaGetDeviceCount(&num_devices);
S
shengjh 已提交
379 380
    fiu_do_on("ValidationUtil.ValidateGpuIndex.get_device_count_fail", cuda_err = cudaError::cudaErrorUnknown);

S
starlord 已提交
381
    if (cuda_err != cudaSuccess) {
S
starlord 已提交
382 383 384
        std::string msg = "Failed to get gpu card number, cuda error:" + std::to_string(cuda_err);
        SERVER_LOG_ERROR << msg;
        return Status(SERVER_UNEXPECTED_ERROR, msg);
385 386
    }

Z
zhiru 已提交
387
    if (gpu_index >= num_devices) {
S
starlord 已提交
388 389 390
        std::string msg = "Invalid gpu index: " + std::to_string(gpu_index);
        SERVER_LOG_ERROR << msg;
        return Status(SERVER_INVALID_ARGUMENT, msg);
391
    }
Y
youny626 已提交
392
#endif
393

S
starlord 已提交
394
    return Status::OK();
395 396
}

G
groot 已提交
397
#ifdef MILVUS_GPU_VERSION
G
groot 已提交
398

S
starlord 已提交
399
Status
400
ValidationUtil::GetGpuMemory(int32_t gpu_index, size_t& memory) {
S
shengjh 已提交
401 402
    fiu_return_on("ValidationUtil.GetGpuMemory.return_error", Status(SERVER_UNEXPECTED_ERROR, ""));

403 404 405
    cudaDeviceProp deviceProp;
    auto cuda_err = cudaGetDeviceProperties(&deviceProp, gpu_index);
    if (cuda_err) {
Y
youny626 已提交
406 407
        std::string msg = "Failed to get gpu properties for gpu" + std::to_string(gpu_index) +
                          " , cuda error:" + std::to_string(cuda_err);
S
starlord 已提交
408 409
        SERVER_LOG_ERROR << msg;
        return Status(SERVER_UNEXPECTED_ERROR, msg);
410 411 412
    }

    memory = deviceProp.totalGlobalMem;
S
starlord 已提交
413
    return Status::OK();
414
}
G
groot 已提交
415

G
groot 已提交
416
#endif
417

S
starlord 已提交
418
Status
S
starlord 已提交
419
ValidationUtil::ValidateIpAddress(const std::string& ip_address) {
Z
zhiru 已提交
420 421 422
    struct in_addr address;

    int result = inet_pton(AF_INET, ip_address.c_str(), &address);
S
shengjh 已提交
423
    fiu_do_on("ValidationUtil.ValidateIpAddress.error_ip_result", result = 2);
Z
zhiru 已提交
424

Z
zhiru 已提交
425
    switch (result) {
S
starlord 已提交
426 427
        case 1:
            return Status::OK();
S
starlord 已提交
428 429 430 431 432 433 434 435 436 437
        case 0: {
            std::string msg = "Invalid IP address: " + ip_address;
            SERVER_LOG_ERROR << msg;
            return Status(SERVER_INVALID_ARGUMENT, msg);
        }
        default: {
            std::string msg = "IP address conversion error: " + ip_address;
            SERVER_LOG_ERROR << msg;
            return Status(SERVER_UNEXPECTED_ERROR, msg);
        }
Z
zhiru 已提交
438 439 440
    }
}

S
starlord 已提交
441
Status
S
starlord 已提交
442
ValidationUtil::ValidateStringIsNumber(const std::string& str) {
Y
yudong.cai 已提交
443 444
    if (str.empty() || !std::all_of(str.begin(), str.end(), ::isdigit)) {
        return Status(SERVER_INVALID_ARGUMENT, "Invalid number");
Z
zhiru 已提交
445
    }
Y
yudong.cai 已提交
446
    try {
B
BossZou 已提交
447
        int64_t value = std::stol(str);
S
shengjh 已提交
448
        fiu_do_on("ValidationUtil.ValidateStringIsNumber.throw_exception", throw std::exception());
449 450 451
        if (value < 0) {
            return Status(SERVER_INVALID_ARGUMENT, "Negative number");
        }
S
starlord 已提交
452
    } catch (...) {
Y
yudong.cai 已提交
453
        return Status(SERVER_INVALID_ARGUMENT, "Invalid number");
Z
zhiru 已提交
454
    }
Y
yudong.cai 已提交
455
    return Status::OK();
Z
zhiru 已提交
456 457
}

S
starlord 已提交
458
Status
S
starlord 已提交
459
ValidationUtil::ValidateStringIsBool(const std::string& str) {
S
shengjh 已提交
460
    fiu_return_on("ValidateStringNotBool", Status(SERVER_INVALID_ARGUMENT, "Invalid boolean: " + str));
Y
yudong.cai 已提交
461 462
    std::string s = str;
    std::transform(s.begin(), s.end(), s.begin(), ::tolower);
S
starlord 已提交
463
    if (s == "true" || s == "on" || s == "yes" || s == "1" || s == "false" || s == "off" || s == "no" || s == "0" ||
Y
yudong.cai 已提交
464
        s.empty()) {
S
starlord 已提交
465
        return Status::OK();
Z
zhiru 已提交
466
    }
S
starlord 已提交
467
    return Status(SERVER_INVALID_ARGUMENT, "Invalid boolean: " + str);
Z
zhiru 已提交
468 469
}

S
starlord 已提交
470
Status
S
starlord 已提交
471
ValidationUtil::ValidateStringIsFloat(const std::string& str) {
Y
yudong.cai 已提交
472 473
    try {
        float val = std::stof(str);
474 475 476
        if (val < 0.0) {
            return Status(SERVER_INVALID_ARGUMENT, "Negative float: " + str);
        }
S
starlord 已提交
477
    } catch (...) {
Y
yudong.cai 已提交
478
        return Status(SERVER_INVALID_ARGUMENT, "Invalid float: " + str);
Z
zhiru 已提交
479
    }
Y
yudong.cai 已提交
480
    return Status::OK();
Z
zhiru 已提交
481 482
}

S
starlord 已提交
483
Status
S
starlord 已提交
484
ValidationUtil::ValidateDbURI(const std::string& uri) {
Z
zhiru 已提交
485 486 487 488 489 490
    std::string dialectRegex = "(.*)";
    std::string usernameRegex = "(.*)";
    std::string passwordRegex = "(.*)";
    std::string hostRegex = "(.*)";
    std::string portRegex = "(.*)";
    std::string dbNameRegex = "(.*)";
S
starlord 已提交
491 492
    std::string uriRegexStr = dialectRegex + "\\:\\/\\/" + usernameRegex + "\\:" + passwordRegex + "\\@" + hostRegex +
                              "\\:" + portRegex + "\\/" + dbNameRegex;
Z
zhiru 已提交
493 494 495 496 497 498 499 500 501 502 503 504 505
    std::regex uriRegex(uriRegexStr);
    std::smatch pieces_match;

    bool okay = true;

    if (std::regex_match(uri, pieces_match, uriRegex)) {
        std::string dialect = pieces_match[1].str();
        std::transform(dialect.begin(), dialect.end(), dialect.begin(), ::tolower);
        if (dialect.find("mysql") == std::string::npos && dialect.find("sqlite") == std::string::npos) {
            SERVER_LOG_ERROR << "Invalid dialect in URI: dialect = " << dialect;
            okay = false;
        }

S
starlord 已提交
506 507 508 509 510 511 512 513 514 515 516
        /*
         *      Could be DNS, skip checking
         *
                std::string host = pieces_match[4].str();
                if (!host.empty() && host != "localhost") {
                    if (ValidateIpAddress(host) != SERVER_SUCCESS) {
                        SERVER_LOG_ERROR << "Invalid host ip address in uri = " << host;
                        okay = false;
                    }
                }
        */
Z
zhiru 已提交
517 518 519

        std::string port = pieces_match[5].str();
        if (!port.empty()) {
S
starlord 已提交
520 521
            auto status = ValidateStringIsNumber(port);
            if (!status.ok()) {
Z
zhiru 已提交
522 523 524 525
                SERVER_LOG_ERROR << "Invalid port in uri = " << port;
                okay = false;
            }
        }
S
starlord 已提交
526
    } else {
Z
zhiru 已提交
527 528 529 530
        SERVER_LOG_ERROR << "Wrong URI format: URI = " << uri;
        okay = false;
    }

S
starlord 已提交
531
    return (okay ? Status::OK() : Status(SERVER_INVALID_ARGUMENT, "Invalid db backend uri"));
Z
zhiru 已提交
532 533
}

534 535 536 537 538 539 540 541 542 543 544 545 546
Status
ValidationUtil::ValidateStoragePath(const std::string& path) {
    // Validate storage path if is valid, only correct absolute path will be validated pass
    // Invalid path only contain character[a-zA-Z], number[0-9], '-', and '_',
    // and path must start with '/'.
    // examples below are invalid
    // '/a//a', '/a--/a', '/-a/a', '/a@#/a', 'aaa/sfs'
    std::string path_pattern = "^\\/(\\w+-?\\/?)+$";
    std::regex regex(path_pattern);

    return std::regex_match(path, regex) ? Status::OK() : Status(SERVER_INVALID_ARGUMENT, "Invalid file path");
}

S
starlord 已提交
547 548
}  // namespace server
}  // namespace milvus