Utils.cpp 9.7 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 "db/Utils.h"
X
Xu Peng 已提交
13

S
shengjh 已提交
14
#include <fiu-local.h>
15

G
groot 已提交
16
#include <unistd.h>
S
starlord 已提交
17
#include <boost/filesystem.hpp>
X
Xu Peng 已提交
18
#include <chrono>
G
groot 已提交
19
#include <memory>
S
starlord 已提交
20
#include <mutex>
21
#include <regex>
S
starlord 已提交
22
#include <vector>
X
Xu Peng 已提交
23

C
Cai Yudong 已提交
24
#include "cache/CpuCacheMgr.h"
G
groot 已提交
25 26
#include "db/Types.h"

C
Cai Yudong 已提交
27 28 29
#ifdef MILVUS_GPU_VERSION
#include "cache/GpuCacheMgr.h"
#endif
G
groot 已提交
30

31
#include "config/Config.h"
C
Cai Yudong 已提交
32
//#include "storage/s3/S3ClientWrapper.h"
33 34 35
#include "utils/CommonUtil.h"
#include "utils/Log.h"

36 37
#include <map>

J
jinhai 已提交
38
namespace milvus {
X
Xu Peng 已提交
39 40 41
namespace engine {
namespace utils {

S
starlord 已提交
42 43
namespace {

S
starlord 已提交
44
const char* TABLES_FOLDER = "/tables/";
S
starlord 已提交
45

C
Cai Yudong 已提交
46
static std::string
J
Jin Hai 已提交
47 48
ConstructParentFolder(const std::string& db_path, const meta::SegmentSchema& table_file) {
    std::string table_path = db_path + TABLES_FOLDER + table_file.collection_id_;
49
    std::string partition_path = table_path + "/" + table_file.segment_id_;
S
starlord 已提交
50 51 52
    return partition_path;
}

S
starlord 已提交
53
}  // namespace
S
starlord 已提交
54

S
starlord 已提交
55 56
int64_t
GetMicroSecTimeStamp() {
X
Xu Peng 已提交
57
    auto now = std::chrono::system_clock::now();
S
starlord 已提交
58
    auto micros = std::chrono::duration_cast<std::chrono::microseconds>(now.time_since_epoch()).count();
X
Xu Peng 已提交
59 60 61 62

    return micros;
}

S
starlord 已提交
63
Status
64
CreateCollectionPath(const DBMetaOptions& options, const std::string& collection_id) {
S
starlord 已提交
65
    std::string db_path = options.path_;
J
Jin Hai 已提交
66
    std::string table_path = db_path + TABLES_FOLDER + collection_id;
67
    auto status = CommonUtil::CreateDirectory(table_path);
S
starlord 已提交
68
    if (!status.ok()) {
69
        LOG_ENGINE_ERROR_ << status.message();
S
starlord 已提交
70
        return status;
S
starlord 已提交
71 72 73 74
    }
    return Status::OK();
}

S
starlord 已提交
75
Status
G
groot 已提交
76
DeleteCollectionPath(const DBMetaOptions& options, const std::string& collection_id, bool force) {
C
Cai Yudong 已提交
77 78 79 80 81 82 83
    std::string table_path = options.path_ + TABLES_FOLDER + collection_id;
    if (force) {
        boost::filesystem::remove_all(table_path);
        LOG_ENGINE_DEBUG_ << "Remove collection folder: " << table_path;
    } else if (boost::filesystem::exists(table_path) && boost::filesystem::is_empty(table_path)) {
        boost::filesystem::remove_all(table_path);
        LOG_ENGINE_DEBUG_ << "Remove collection folder: " << table_path;
S
starlord 已提交
84 85
    }

C
Cai Yudong 已提交
86 87 88
    // bool s3_enable = false;
    // server::Config& config = server::Config::GetInstance();
    // config.GetStorageConfigS3Enable(s3_enable);
C
Cai Yudong 已提交
89

C
Cai Yudong 已提交
90 91
    // if (s3_enable) {
    //     std::string table_path = options.path_ + TABLES_FOLDER + collection_id;
C
Cai Yudong 已提交
92

C
Cai Yudong 已提交
93 94 95 96 97 98
    //     auto& storage_inst = milvus::storage::S3ClientWrapper::GetInstance();
    //     Status stat = storage_inst.DeleteObjects(table_path);
    //     if (!stat.ok()) {
    //         return stat;
    //     }
    // }
C
Cai Yudong 已提交
99

S
starlord 已提交
100 101 102
    return Status::OK();
}

S
starlord 已提交
103
Status
104
CreateCollectionFilePath(const DBMetaOptions& options, meta::SegmentSchema& table_file) {
C
Cai Yudong 已提交
105
    std::string parent_path = ConstructParentFolder(options.path_, table_file);
S
starlord 已提交
106

107
    auto status = CommonUtil::CreateDirectory(parent_path);
108
    fiu_do_on("CreateCollectionFilePath.fail_create", status = Status(DB_INVALID_PATH, ""));
S
starlord 已提交
109
    if (!status.ok()) {
110
        LOG_ENGINE_ERROR_ << status.message();
S
starlord 已提交
111
        return status;
S
starlord 已提交
112 113 114 115 116 117 118
    }

    table_file.location_ = parent_path + "/" + table_file.file_id_;

    return Status::OK();
}

S
starlord 已提交
119
Status
G
groot 已提交
120
GetCollectionFilePath(const DBMetaOptions& options, meta::SegmentSchema& table_file) {
S
starlord 已提交
121
    std::string parent_path = ConstructParentFolder(options.path_, table_file);
S
starlord 已提交
122
    std::string file_path = parent_path + "/" + table_file.file_id_;
C
Cai Yudong 已提交
123

C
Cai Yudong 已提交
124 125 126 127 128 129 130 131 132
    // bool s3_enable = false;
    // server::Config& config = server::Config::GetInstance();
    // config.GetStorageConfigS3Enable(s3_enable);
    // fiu_do_on("GetCollectionFilePath.enable_s3", s3_enable = true);
    // if (s3_enable) {
    //     /* need not check file existence */
    //     table_file.location_ = file_path;
    //     return Status::OK();
    // }
C
Cai Yudong 已提交
133

134
    if (boost::filesystem::exists(parent_path)) {
S
starlord 已提交
135 136
        table_file.location_ = file_path;
        return Status::OK();
S
starlord 已提交
137 138
    }

J
Jin Hai 已提交
139
    std::string msg = "Collection file doesn't exist: " + file_path;
G
groot 已提交
140
    if (table_file.file_size_ > 0) {  // no need to pop error for empty file
141
        LOG_ENGINE_ERROR_ << msg << " in path: " << options.path_ << " for collection: " << table_file.collection_id_;
G
groot 已提交
142
    }
S
starlord 已提交
143

S
starlord 已提交
144
    return Status(DB_ERROR, msg);
S
starlord 已提交
145 146
}

S
starlord 已提交
147
Status
G
groot 已提交
148 149
DeleteCollectionFilePath(const DBMetaOptions& options, meta::SegmentSchema& table_file) {
    utils::GetCollectionFilePath(options, table_file);
S
starlord 已提交
150 151 152 153
    boost::filesystem::remove(table_file.location_);
    return Status::OK();
}

154
Status
J
Jin Hai 已提交
155
DeleteSegment(const DBMetaOptions& options, meta::SegmentSchema& table_file) {
G
groot 已提交
156
    utils::GetCollectionFilePath(options, table_file);
157 158 159 160 161 162 163 164 165 166 167 168 169
    std::string segment_dir;
    GetParentPath(table_file.location_, segment_dir);
    boost::filesystem::remove_all(segment_dir);
    return Status::OK();
}

Status
GetParentPath(const std::string& path, std::string& parent_path) {
    boost::filesystem::path p(path);
    parent_path = p.parent_path().string();
    return Status::OK();
}

S
starlord 已提交
170
bool
171
IsSameIndex(const CollectionIndex& index1, const CollectionIndex& index2) {
172
    return index1.engine_type_ == index2.engine_type_ && index1.extra_params_ == index2.extra_params_ &&
S
starlord 已提交
173
           index1.metric_type_ == index2.metric_type_;
174 175
}

176 177 178 179 180
bool
IsRawIndexType(int32_t type) {
    return (type == (int32_t)EngineType::FAISS_IDMAP) || (type == (int32_t)EngineType::FAISS_BIN_IDMAP);
}

181 182 183 184
bool
IsBinaryMetricType(int32_t metric_type) {
    return (metric_type == (int32_t)engine::MetricType::HAMMING) ||
           (metric_type == (int32_t)engine::MetricType::JACCARD) ||
185 186
           (metric_type == (int32_t)engine::MetricType::SUBSTRUCTURE) ||
           (metric_type == (int32_t)engine::MetricType::SUPERSTRUCTURE) ||
187 188 189
           (metric_type == (int32_t)engine::MetricType::TANIMOTO);
}

S
starlord 已提交
190
meta::DateT
S
starlord 已提交
191
GetDate(const std::time_t& t, int day_delta) {
192 193 194 195 196 197
    struct tm ltm;
    localtime_r(&t, &ltm);
    if (day_delta > 0) {
        do {
            ++ltm.tm_mday;
            --day_delta;
S
starlord 已提交
198
        } while (day_delta > 0);
199 200 201 202 203
        mktime(&ltm);
    } else if (day_delta < 0) {
        do {
            --ltm.tm_mday;
            ++day_delta;
S
starlord 已提交
204
        } while (day_delta < 0);
205 206
        mktime(&ltm);
    }
S
starlord 已提交
207
    return ltm.tm_year * 10000 + ltm.tm_mon * 100 + ltm.tm_mday;
208 209
}

S
starlord 已提交
210 211
meta::DateT
GetDateWithDelta(int day_delta) {
212 213 214
    return GetDate(std::time(nullptr), day_delta);
}

S
starlord 已提交
215 216
meta::DateT
GetDate() {
217 218 219
    return GetDate(std::time(nullptr), 0);
}

220
// URI format: dialect://username:password@host:port/database
S
starlord 已提交
221
Status
S
starlord 已提交
222
ParseMetaUri(const std::string& uri, MetaUriInfo& info) {
223 224 225 226 227 228
    std::string dialect_regex = "(.*)";
    std::string username_tegex = "(.*)";
    std::string password_regex = "(.*)";
    std::string host_regex = "(.*)";
    std::string port_regex = "(.*)";
    std::string db_name_regex = "(.*)";
S
starlord 已提交
229 230
    std::string uri_regex_str = dialect_regex + "\\:\\/\\/" + username_tegex + "\\:" + password_regex + "\\@" +
                                host_regex + "\\:" + port_regex + "\\/" + db_name_regex;
231 232 233 234 235 236 237 238 239 240 241 242

    std::regex uri_regex(uri_regex_str);
    std::smatch pieces_match;

    if (std::regex_match(uri, pieces_match, uri_regex)) {
        info.dialect_ = pieces_match[1].str();
        info.username_ = pieces_match[2].str();
        info.password_ = pieces_match[3].str();
        info.host_ = pieces_match[4].str();
        info.port_ = pieces_match[5].str();
        info.db_name_ = pieces_match[6].str();

S
starlord 已提交
243
        // TODO(myh): verify host, port...
244 245 246 247 248 249 250
    } else {
        return Status(DB_INVALID_META_URI, "Invalid meta uri: " + uri);
    }

    return Status::OK();
}

251 252 253
std::string
GetIndexName(int32_t index_type) {
    static std::map<int32_t, std::string> index_type_name = {
254 255 256 257 258
        {(int32_t)engine::EngineType::FAISS_IDMAP, "FLAT"},
        {(int32_t)engine::EngineType::FAISS_IVFFLAT, "IVF_FLAT"},
        {(int32_t)engine::EngineType::FAISS_IVFSQ8, "IVF_SQ8"},
        {(int32_t)engine::EngineType::FAISS_IVFSQ8H, "IVF_SQ8_HYBRID"},
        {(int32_t)engine::EngineType::FAISS_PQ, "IVF_PQ"},
259
#ifdef MILVUS_SUPPORT_SPTAG
260 261
        {(int32_t)engine::EngineType::SPTAG_KDT, "SPTAG_KDT_RNT"},
        {(int32_t)engine::EngineType::SPTAG_BKT, "SPTAG_BKT_RNT"},
262
#endif
263 264
        {(int32_t)engine::EngineType::FAISS_BIN_IDMAP, "BIN_FLAT"},
        {(int32_t)engine::EngineType::FAISS_BIN_IVFFLAT, "BIN_IVF_FLAT"},
G
groot 已提交
265
        {(int32_t)engine::EngineType::HNSW, "HNSW"},
266
        {(int32_t)engine::EngineType::NSG_MIX, "NSG"},
G
groot 已提交
267
        {(int32_t)engine::EngineType::ANNOY, "ANNOY"}};
268 269 270 271 272 273 274 275

    if (index_type_name.find(index_type) == index_type_name.end()) {
        return "Unknow";
    }

    return index_type_name[index_type];
}

G
groot 已提交
276 277 278 279 280 281 282 283 284 285 286 287 288 289
void
SendExitSignal() {
    LOG_SERVER_INFO_ << "Send SIGUSR2 signal to exit";
    pid_t pid = getpid();
    kill(pid, SIGUSR2);
}

void
ExitOnWriteError(Status& status) {
    if (status.code() == SERVER_WRITE_ERROR) {
        utils::SendExitSignal();
    }
}

C
Cai Yudong 已提交
290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307
void
EraseFromCache(const std::string& item_key) {
    if (item_key.empty()) {
        LOG_SERVER_ERROR_ << "Empty key cannot be erased from cache";
        return;
    }

    cache::CpuCacheMgr::GetInstance()->EraseItem(item_key);

#ifdef MILVUS_GPU_VERSION
    server::Config& config = server::Config::GetInstance();
    std::vector<int64_t> gpus;
    config.GetGpuResourceConfigSearchResources(gpus);
    for (auto& gpu : gpus) {
        cache::GpuCacheMgr::GetInstance(gpu)->EraseItem(item_key);
    }
#endif
}
S
starlord 已提交
308 309 310
}  // namespace utils
}  // namespace engine
}  // namespace milvus