ValidationUtil.cpp 9.4 KB
Newer Older
J
jinhai 已提交
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements.  See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership.  The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// 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.


S
starlord 已提交
19
#include "db/engine/ExecutionEngine.h"
J
jinhai 已提交
20 21 22
#include "ValidationUtil.h"
#include "Log.h"

23
#include <cuda_runtime.h>
Z
zhiru 已提交
24 25 26 27
#include <arpa/inet.h>
#include <regex>
#include <algorithm>

Z
zhiru 已提交
28

J
jinhai 已提交
29 30 31 32
namespace zilliz {
namespace milvus {
namespace server {

33 34 35
constexpr size_t TABLE_NAME_SIZE_LIMIT = 255;
constexpr int64_t TABLE_DIMENSION_LIMIT = 16384;
constexpr int32_t INDEX_FILE_SIZE_LIMIT = 4096; //index trigger size max = 4096 MB
J
jinhai 已提交
36

S
starlord 已提交
37
Status
38
ValidationUtil::ValidateTableName(const std::string &table_name) {
J
jinhai 已提交
39 40 41

    // Table name shouldn't be empty.
    if (table_name.empty()) {
S
starlord 已提交
42 43 44
        std::string msg = "Empty table name";
        SERVER_LOG_ERROR << msg;
        return Status(SERVER_INVALID_TABLE_NAME, msg);
J
jinhai 已提交
45 46 47
    }

    // Table name size shouldn't exceed 16384.
48
    if (table_name.size() > TABLE_NAME_SIZE_LIMIT) {
S
starlord 已提交
49 50 51
        std::string msg = "Table name size exceed the limitation";
        SERVER_LOG_ERROR << msg;
        return Status(SERVER_INVALID_TABLE_NAME, msg);
J
jinhai 已提交
52 53 54 55 56
    }

    // Table name first character should be underscore or character.
    char first_char = table_name[0];
    if (first_char != '_' && std::isalpha(first_char) == 0) {
S
starlord 已提交
57 58 59
        std::string msg = "Table name first character isn't underscore or character";
        SERVER_LOG_ERROR << msg;
        return Status(SERVER_INVALID_TABLE_NAME, msg);
J
jinhai 已提交
60 61 62 63 64 65
    }

    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) {
S
starlord 已提交
66 67 68
            std::string msg = "Table name character isn't underscore or alphanumber";
            SERVER_LOG_ERROR << msg;
            return Status(SERVER_INVALID_TABLE_NAME, msg);
J
jinhai 已提交
69 70 71
        }
    }

S
starlord 已提交
72
    return Status::OK();
J
jinhai 已提交
73 74
}

S
starlord 已提交
75
Status
76
ValidationUtil::ValidateTableDimension(int64_t dimension) {
77
    if (dimension <= 0 || dimension > TABLE_DIMENSION_LIMIT) {
S
starlord 已提交
78 79 80
        std::string msg = "Table dimension excceed the limitation: " + std::to_string(TABLE_DIMENSION_LIMIT);
        SERVER_LOG_ERROR << msg;
        return Status(SERVER_INVALID_VECTOR_DIMENSION, msg);
Z
zhiru 已提交
81 82
    }
    else {
S
starlord 已提交
83
        return Status::OK();
J
jinhai 已提交
84 85 86
    }
}

S
starlord 已提交
87
Status
88
ValidationUtil::ValidateTableIndexType(int32_t index_type) {
Z
zhiru 已提交
89 90
    int engine_type = (int) engine::EngineType(index_type);
    if (engine_type <= 0 || engine_type > (int) engine::EngineType::MAX_VALUE) {
S
starlord 已提交
91 92 93
        std::string msg = "Invalid index type: " + std::to_string(index_type);
        SERVER_LOG_ERROR << msg;
        return Status(SERVER_INVALID_INDEX_TYPE, msg);
J
jinhai 已提交
94
    }
95

S
starlord 已提交
96
    return Status::OK();
J
jinhai 已提交
97 98
}

S
starlord 已提交
99
Status
S
starlord 已提交
100
ValidationUtil::ValidateTableIndexNlist(int32_t nlist) {
Z
zhiru 已提交
101
    if (nlist <= 0) {
S
starlord 已提交
102 103 104
        std::string msg = "Invalid nlist value: " + std::to_string(nlist);
        SERVER_LOG_ERROR << msg;
        return Status(SERVER_INVALID_INDEX_NLIST, msg);
S
starlord 已提交
105 106
    }

S
starlord 已提交
107
    return Status::OK();
S
starlord 已提交
108 109
}

S
starlord 已提交
110
Status
111
ValidationUtil::ValidateTableIndexFileSize(int64_t index_file_size) {
Z
zhiru 已提交
112
    if (index_file_size <= 0 || index_file_size > INDEX_FILE_SIZE_LIMIT) {
S
starlord 已提交
113 114 115
        std::string msg = "Invalid index file size: " + std::to_string(index_file_size);
        SERVER_LOG_ERROR << msg;
        return Status(SERVER_INVALID_INDEX_FILE_SIZE, msg);
S
starlord 已提交
116 117
    }

S
starlord 已提交
118
    return Status::OK();
S
starlord 已提交
119 120
}

S
starlord 已提交
121
Status
S
starlord 已提交
122
ValidationUtil::ValidateTableIndexMetricType(int32_t metric_type) {
Z
zhiru 已提交
123
    if (metric_type != (int32_t) engine::MetricType::L2 && metric_type != (int32_t) engine::MetricType::IP) {
S
starlord 已提交
124 125 126
        std::string msg = "Invalid metric type: " + std::to_string(metric_type);
        SERVER_LOG_ERROR << msg;
        return Status(SERVER_INVALID_INDEX_METRIC_TYPE, msg);
S
starlord 已提交
127
    }
S
starlord 已提交
128
    return Status::OK();
S
starlord 已提交
129 130
}

S
starlord 已提交
131
Status
Z
zhiru 已提交
132
ValidationUtil::ValidateSearchTopk(int64_t top_k, const engine::meta::TableSchema &table_schema) {
133
    if (top_k <= 0 || top_k > 2048) {
S
starlord 已提交
134 135 136
        std::string msg = "Invalid top k value: " + std::to_string(top_k);
        SERVER_LOG_ERROR << msg;
        return Status(SERVER_INVALID_TOPK, msg);
137 138
    }

S
starlord 已提交
139
    return Status::OK();
140 141
}

S
starlord 已提交
142
Status
Z
zhiru 已提交
143
ValidationUtil::ValidateSearchNprobe(int64_t nprobe, const engine::meta::TableSchema &table_schema) {
144
    if (nprobe <= 0 || nprobe > table_schema.nlist_) {
S
starlord 已提交
145 146 147
        std::string msg = "Invalid nprobe value: " + std::to_string(nprobe);
        SERVER_LOG_ERROR << msg;
        return Status(SERVER_INVALID_NPROBE, msg);
148 149
    }

S
starlord 已提交
150
    return Status::OK();
151 152
}

S
starlord 已提交
153
Status
154 155 156 157
ValidationUtil::ValidateGpuIndex(uint32_t gpu_index) {
    int num_devices = 0;
    auto cuda_err = cudaGetDeviceCount(&num_devices);
    if (cuda_err) {
S
starlord 已提交
158 159 160
        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);
161 162
    }

Z
zhiru 已提交
163
    if (gpu_index >= num_devices) {
S
starlord 已提交
164 165 166
        std::string msg = "Invalid gpu index: " + std::to_string(gpu_index);
        SERVER_LOG_ERROR << msg;
        return Status(SERVER_INVALID_ARGUMENT, msg);
167 168
    }

S
starlord 已提交
169
    return Status::OK();
170 171
}

S
starlord 已提交
172
Status
Z
zhiru 已提交
173
ValidationUtil::GetGpuMemory(uint32_t gpu_index, size_t &memory) {
174 175 176
    cudaDeviceProp deviceProp;
    auto cuda_err = cudaGetDeviceProperties(&deviceProp, gpu_index);
    if (cuda_err) {
S
starlord 已提交
177 178 179
        std::string msg = "Failed to get gpu properties, cuda error:" + std::to_string(cuda_err);
        SERVER_LOG_ERROR << msg;
        return Status(SERVER_UNEXPECTED_ERROR, msg);
180 181 182
    }

    memory = deviceProp.totalGlobalMem;
S
starlord 已提交
183
    return Status::OK();
184 185
}

S
starlord 已提交
186
Status
Z
zhiru 已提交
187
ValidationUtil::ValidateIpAddress(const std::string &ip_address) {
Z
zhiru 已提交
188 189 190 191 192

    struct in_addr address;

    int result = inet_pton(AF_INET, ip_address.c_str(), &address);

Z
zhiru 已提交
193
    switch (result) {
S
starlord 已提交
194 195 196 197 198 199 200 201 202 203 204
        case 1:return Status::OK();
        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 已提交
205 206 207
    }
}

S
starlord 已提交
208
Status
Z
zhiru 已提交
209 210
ValidationUtil::ValidateStringIsNumber(const std::string &string) {
    if (!string.empty() && std::all_of(string.begin(), string.end(), ::isdigit)) {
S
starlord 已提交
211
        return Status::OK();
Z
zhiru 已提交
212 213
    }
    else {
S
starlord 已提交
214
        return Status(SERVER_INVALID_ARGUMENT, "Not a number");
Z
zhiru 已提交
215 216 217
    }
}

S
starlord 已提交
218
Status
Z
zhiru 已提交
219 220 221 222 223
ValidationUtil::ValidateStringIsBool(std::string &str) {
    std::transform(str.begin(), str.end(), str.begin(), ::tolower);
    if (str == "true" || str == "on" || str == "yes" || str == "1" ||
        str == "false" || str == "off" || str == "no" || str == "0" ||
        str.empty()) {
S
starlord 已提交
224
        return Status::OK();
Z
zhiru 已提交
225 226
    }
    else {
S
starlord 已提交
227
        return Status(SERVER_INVALID_ARGUMENT, "Not a boolean: " + str);
Z
zhiru 已提交
228 229 230
    }
}

S
starlord 已提交
231
Status
Z
zhiru 已提交
232
ValidationUtil::ValidateStringIsDouble(const std::string &str, double &val) {
Z
zhiru 已提交
233
    char *end = nullptr;
Z
zhiru 已提交
234 235
    val = std::strtod(str.c_str(), &end);
    if (end != str.c_str() && *end == '\0' && val != HUGE_VAL) {
S
starlord 已提交
236
        return Status::OK();
Z
zhiru 已提交
237 238
    }
    else {
S
starlord 已提交
239
        return Status(SERVER_INVALID_ARGUMENT, "Not a double value: " + str);
Z
zhiru 已提交
240 241 242
    }
}

S
starlord 已提交
243
Status
Z
zhiru 已提交
244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269
ValidationUtil::ValidateDbURI(const std::string &uri) {
    std::string dialectRegex = "(.*)";
    std::string usernameRegex = "(.*)";
    std::string passwordRegex = "(.*)";
    std::string hostRegex = "(.*)";
    std::string portRegex = "(.*)";
    std::string dbNameRegex = "(.*)";
    std::string uriRegexStr = dialectRegex + "\\:\\/\\/" +
        usernameRegex + "\\:" +
        passwordRegex + "\\@" +
        hostRegex + "\\:" +
        portRegex + "\\/" +
        dbNameRegex;
    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;
        }

Z
zhiru 已提交
270 271 272
/*
 *      Could be DNS, skip checking
 *
Z
zhiru 已提交
273 274 275 276 277 278 279
        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 已提交
280
*/
Z
zhiru 已提交
281 282 283

        std::string port = pieces_match[5].str();
        if (!port.empty()) {
S
starlord 已提交
284 285
            auto status = ValidateStringIsNumber(port);
            if (!status.ok()) {
Z
zhiru 已提交
286 287 288 289
                SERVER_LOG_ERROR << "Invalid port in uri = " << port;
                okay = false;
            }
        }
Z
zhiru 已提交
290 291
    }
    else {
Z
zhiru 已提交
292 293 294 295
        SERVER_LOG_ERROR << "Wrong URI format: URI = " << uri;
        okay = false;
    }

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

J
jinhai 已提交
299 300 301
}
}
}