Utils.cpp 6.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.

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

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

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

G
groot 已提交
31 32
namespace {

J
jinhai 已提交
33
const char* TABLES_FOLDER = "/tables/";
G
groot 已提交
34

J
jinhai 已提交
35 36
uint64_t index_file_counter = 0;
std::mutex index_file_counter_mutex;
37

G
groot 已提交
38 39 40 41 42 43 44 45 46
std::string ConstructParentFolder(const std::string& db_path, const meta::TableFileSchema& table_file) {
    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;
}

std::string GetTableFileParentFolder(const DBMetaOptions& options, const meta::TableFileSchema& table_file) {
    uint64_t path_count = options.slave_paths.size() + 1;
    std::string target_path = options.path;
47 48
    uint64_t index = 0;

49
    if(meta::TableFileSchema::NEW_INDEX == table_file.file_type_) {
50 51 52 53 54 55 56 57 58 59 60 61 62
        // 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 已提交
63 64 65 66 67 68 69 70
        target_path = options.slave_paths[index - 1];
    }

    return ConstructParentFolder(target_path, table_file);
}

}

X
Xu Peng 已提交
71 72 73 74 75 76 77 78
long GetMicroSecTimeStamp() {
    auto now = std::chrono::system_clock::now();
    auto micros = std::chrono::duration_cast<std::chrono::microseconds>(
            now.time_since_epoch()).count();

    return micros;
}

G
groot 已提交
79 80 81 82 83 84
Status CreateTablePath(const DBMetaOptions& options, const std::string& table_id) {
    std::string db_path = options.path;
    std::string table_path = db_path + TABLES_FOLDER + table_id;
    auto status = server::CommonUtil::CreateDirectory(table_path);
    if (status != 0) {
        ENGINE_LOG_ERROR << "Create directory " << table_path << " Error";
G
groot 已提交
85
        return Status(DB_ERROR, "Failed to create table path");
G
groot 已提交
86 87 88 89 90 91 92
    }

    for(auto& path : options.slave_paths) {
        table_path = path + TABLES_FOLDER + table_id;
        status = server::CommonUtil::CreateDirectory(table_path);
        if (status != 0) {
            ENGINE_LOG_ERROR << "Create directory " << table_path << " Error";
G
groot 已提交
93
            return Status(DB_ERROR, "Failed to create table path");
G
groot 已提交
94 95 96 97 98 99
        }
    }

    return Status::OK();
}

G
groot 已提交
100 101 102 103 104 105 106 107 108 109 110 111 112 113
Status DeleteTablePath(const DBMetaOptions& options, const std::string& table_id, bool force) {
    std::vector<std::string> paths = options.slave_paths;
    paths.push_back(options.path);

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

    return Status::OK();
}

Status CreateTableFilePath(const DBMetaOptions& options, meta::TableFileSchema& table_file) {
    std::string parent_path = GetTableFileParentFolder(options, table_file);

    auto status = server::CommonUtil::CreateDirectory(parent_path);
    if (status != 0) {
        ENGINE_LOG_ERROR << "Create directory " << parent_path << " Error";
G
groot 已提交
125
        return Status(DB_ERROR, "Failed to create partition directory");
G
groot 已提交
126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149
    }

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

    return Status::OK();
}

Status GetTableFilePath(const DBMetaOptions& options, meta::TableFileSchema& table_file) {
    std::string parent_path = ConstructParentFolder(options.path, table_file);
    std::string file_path = parent_path + "/" + table_file.file_id_;
    if(boost::filesystem::exists(file_path)) {
        table_file.location_ = file_path;
        return Status::OK();
    } else {
        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 已提交
150
    std::string msg = "Table file doesn't exist: " + file_path;
151
    ENGINE_LOG_ERROR << msg;
G
groot 已提交
152
    return Status(DB_ERROR, msg);
G
groot 已提交
153 154 155 156 157 158 159 160
}

Status DeleteTableFilePath(const DBMetaOptions& options, meta::TableFileSchema& table_file) {
    utils::GetTableFilePath(options, table_file);
    boost::filesystem::remove(table_file.location_);
    return Status::OK();
}

161 162
bool IsSameIndex(const TableIndex& index1, const TableIndex& index2) {
    return index1.engine_type_ == index2.engine_type_
G
groot 已提交
163 164
        && index1.nlist_ == index2.nlist_
        && index1.metric_type_ == index2.metric_type_;
165 166
}

167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195
meta::DateT GetDate(const std::time_t& t, int day_delta) {
    struct tm ltm;
    localtime_r(&t, &ltm);
    if (day_delta > 0) {
        do {
            ++ltm.tm_mday;
            --day_delta;
        } while(day_delta > 0);
        mktime(&ltm);
    } else if (day_delta < 0) {
        do {
            --ltm.tm_mday;
            ++day_delta;
        } while(day_delta < 0);
        mktime(&ltm);
    } else {
        ltm.tm_mday;
    }
    return ltm.tm_year*10000 + ltm.tm_mon*100 + ltm.tm_mday;
}

meta::DateT GetDateWithDelta(int day_delta) {
    return GetDate(std::time(nullptr), day_delta);
}

meta::DateT GetDate() {
    return GetDate(std::time(nullptr), 0);
}

X
Xu Peng 已提交
196 197
} // namespace utils
} // namespace engine
J
jinhai 已提交
198
} // namespace milvus
X
Xu Peng 已提交
199
} // namespace zilliz