Utils.cpp 7.6 KB
Newer Older
J
jinhai 已提交
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
// 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.

G
groot 已提交
18
#include "db/Utils.h"
G
groot 已提交
19
#include "utils/CommonUtil.h"
G
groot 已提交
20
#include "utils/Log.h"
X
Xu Peng 已提交
21

G
groot 已提交
22
#include <boost/filesystem.hpp>
X
Xu Peng 已提交
23
#include <chrono>
G
groot 已提交
24
#include <mutex>
25
#include <regex>
G
groot 已提交
26
#include <vector>
X
Xu Peng 已提交
27 28

namespace zilliz {
J
jinhai 已提交
29
namespace milvus {
X
Xu Peng 已提交
30 31 32
namespace engine {
namespace utils {

G
groot 已提交
33 34
namespace {

G
groot 已提交
35
const char* TABLES_FOLDER = "/tables/";
G
groot 已提交
36

J
jinhai 已提交
37 38
uint64_t index_file_counter = 0;
std::mutex index_file_counter_mutex;
39

G
groot 已提交
40
std::string
G
groot 已提交
41
ConstructParentFolder(const std::string& db_path, const meta::TableFileSchema& table_file) {
G
groot 已提交
42 43 44 45 46
    std::string table_path = db_path + TABLES_FOLDER + table_file.table_id_;
    std::string partition_path = table_path + "/" + std::to_string(table_file.date_);
    return partition_path;
}

G
groot 已提交
47
std::string
G
groot 已提交
48
GetTableFileParentFolder(const DBMetaOptions& options, const meta::TableFileSchema& table_file) {
G
groot 已提交
49 50
    uint64_t path_count = options.slave_paths_.size() + 1;
    std::string target_path = options.path_;
51 52
    uint64_t index = 0;

G
groot 已提交
53
    if (meta::TableFileSchema::NEW_INDEX == table_file.file_type_) {
54 55 56 57 58 59 60 61 62 63 64 65 66
        // index file is large file and to be persisted permanently
        // we need to distribute index files to each db_path averagely
        // round robin according to a file counter
        std::lock_guard<std::mutex> lock(index_file_counter_mutex);
        index = index_file_counter % path_count;
        index_file_counter++;
    } else {
        // for other type files, they could be merged or deleted
        // so we round robin according to their file id
        index = table_file.id_ % path_count;
    }

    if (index > 0) {
G
groot 已提交
67
        target_path = options.slave_paths_[index - 1];
G
groot 已提交
68 69 70 71 72
    }

    return ConstructParentFolder(target_path, table_file);
}

G
groot 已提交
73
}  // namespace
G
groot 已提交
74

G
groot 已提交
75 76
int64_t
GetMicroSecTimeStamp() {
X
Xu Peng 已提交
77
    auto now = std::chrono::system_clock::now();
G
groot 已提交
78
    auto micros = std::chrono::duration_cast<std::chrono::microseconds>(now.time_since_epoch()).count();
X
Xu Peng 已提交
79 80 81 82

    return micros;
}

G
groot 已提交
83
Status
G
groot 已提交
84
CreateTablePath(const DBMetaOptions& options, const std::string& table_id) {
G
groot 已提交
85
    std::string db_path = options.path_;
G
groot 已提交
86 87
    std::string table_path = db_path + TABLES_FOLDER + table_id;
    auto status = server::CommonUtil::CreateDirectory(table_path);
G
groot 已提交
88 89 90
    if (!status.ok()) {
        ENGINE_LOG_ERROR << status.message();
        return status;
G
groot 已提交
91 92
    }

G
groot 已提交
93
    for (auto& path : options.slave_paths_) {
G
groot 已提交
94 95
        table_path = path + TABLES_FOLDER + table_id;
        status = server::CommonUtil::CreateDirectory(table_path);
G
groot 已提交
96 97 98
        if (!status.ok()) {
            ENGINE_LOG_ERROR << status.message();
            return status;
G
groot 已提交
99 100 101 102 103 104
        }
    }

    return Status::OK();
}

G
groot 已提交
105
Status
G
groot 已提交
106
DeleteTablePath(const DBMetaOptions& options, const std::string& table_id, bool force) {
G
groot 已提交
107 108
    std::vector<std::string> paths = options.slave_paths_;
    paths.push_back(options.path_);
G
groot 已提交
109

G
groot 已提交
110
    for (auto& path : paths) {
G
groot 已提交
111
        std::string table_path = path + TABLES_FOLDER + table_id;
G
groot 已提交
112
        if (force) {
G
groot 已提交
113 114
            boost::filesystem::remove_all(table_path);
            ENGINE_LOG_DEBUG << "Remove table folder: " << table_path;
G
groot 已提交
115
        } else if (boost::filesystem::exists(table_path) && boost::filesystem::is_empty(table_path)) {
G
groot 已提交
116 117 118
            boost::filesystem::remove_all(table_path);
            ENGINE_LOG_DEBUG << "Remove table folder: " << table_path;
        }
G
groot 已提交
119 120 121 122 123
    }

    return Status::OK();
}

G
groot 已提交
124
Status
G
groot 已提交
125
CreateTableFilePath(const DBMetaOptions& options, meta::TableFileSchema& table_file) {
G
groot 已提交
126 127 128
    std::string parent_path = GetTableFileParentFolder(options, table_file);

    auto status = server::CommonUtil::CreateDirectory(parent_path);
G
groot 已提交
129 130 131
    if (!status.ok()) {
        ENGINE_LOG_ERROR << status.message();
        return status;
G
groot 已提交
132 133 134 135 136 137 138
    }

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

    return Status::OK();
}

G
groot 已提交
139
Status
G
groot 已提交
140
GetTableFilePath(const DBMetaOptions& options, meta::TableFileSchema& table_file) {
G
groot 已提交
141
    std::string parent_path = ConstructParentFolder(options.path_, table_file);
G
groot 已提交
142
    std::string file_path = parent_path + "/" + table_file.file_id_;
G
groot 已提交
143
    if (boost::filesystem::exists(file_path)) {
G
groot 已提交
144 145
        table_file.location_ = file_path;
        return Status::OK();
G
groot 已提交
146 147 148 149 150 151 152 153
    }

    for (auto& path : options.slave_paths_) {
        parent_path = ConstructParentFolder(path, table_file);
        file_path = parent_path + "/" + table_file.file_id_;
        if (boost::filesystem::exists(file_path)) {
            table_file.location_ = file_path;
            return Status::OK();
G
groot 已提交
154 155 156
        }
    }

G
groot 已提交
157
    std::string msg = "Table file doesn't exist: " + file_path;
G
groot 已提交
158
    ENGINE_LOG_ERROR << msg << " in path: " << options.path_ << " for table: " << table_file.table_id_;
G
groot 已提交
159

G
groot 已提交
160
    return Status(DB_ERROR, msg);
G
groot 已提交
161 162
}

G
groot 已提交
163
Status
G
groot 已提交
164
DeleteTableFilePath(const DBMetaOptions& options, meta::TableFileSchema& table_file) {
G
groot 已提交
165 166 167 168 169
    utils::GetTableFilePath(options, table_file);
    boost::filesystem::remove(table_file.location_);
    return Status::OK();
}

G
groot 已提交
170
bool
G
groot 已提交
171 172 173
IsSameIndex(const TableIndex& index1, const TableIndex& index2) {
    return index1.engine_type_ == index2.engine_type_ && index1.nlist_ == index2.nlist_ &&
           index1.metric_type_ == index2.metric_type_;
174 175
}

G
groot 已提交
176
meta::DateT
G
groot 已提交
177
GetDate(const std::time_t& t, int day_delta) {
178 179 180 181 182 183
    struct tm ltm;
    localtime_r(&t, &ltm);
    if (day_delta > 0) {
        do {
            ++ltm.tm_mday;
            --day_delta;
G
groot 已提交
184
        } while (day_delta > 0);
185 186 187 188 189
        mktime(&ltm);
    } else if (day_delta < 0) {
        do {
            --ltm.tm_mday;
            ++day_delta;
G
groot 已提交
190
        } while (day_delta < 0);
191 192 193 194
        mktime(&ltm);
    } else {
        ltm.tm_mday;
    }
G
groot 已提交
195
    return ltm.tm_year * 10000 + ltm.tm_mon * 100 + ltm.tm_mday;
196 197
}

G
groot 已提交
198 199
meta::DateT
GetDateWithDelta(int day_delta) {
200 201 202
    return GetDate(std::time(nullptr), day_delta);
}

G
groot 已提交
203 204
meta::DateT
GetDate() {
205 206 207
    return GetDate(std::time(nullptr), 0);
}

208
// URI format: dialect://username:password@host:port/database
G
groot 已提交
209
Status
G
groot 已提交
210
ParseMetaUri(const std::string& uri, MetaUriInfo& info) {
211 212 213 214 215 216
    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 = "(.*)";
G
groot 已提交
217 218
    std::string uri_regex_str = dialect_regex + "\\:\\/\\/" + username_tegex + "\\:" + password_regex + "\\@" +
                                host_regex + "\\:" + port_regex + "\\/" + db_name_regex;
219 220 221 222 223 224 225 226 227 228 229 230

    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();

G
groot 已提交
231
        // TODO: verify host, port...
232 233 234 235 236 237 238
    } else {
        return Status(DB_INVALID_META_URI, "Invalid meta uri: " + uri);
    }

    return Status::OK();
}

G
groot 已提交
239 240 241 242
}  // namespace utils
}  // namespace engine
}  // namespace milvus
}  // namespace zilliz