代码评注赛初阶段成果提交火箭队 #2

Open
saltyfish wants to merge 160 commits from saltyfish/mindspore2022:r.19 into master
1 changed files with 724 additions and 0 deletions
Showing only changes of commit 3b4c0d98a0 - Show all commits

View File

@ -0,0 +1,724 @@
/**
* Copyright 2019 Huawei Technologies Co., Ltd
*
* 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
*
* 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.
*/
#include "minddata/mindrecord/include/shard_header.h"//按照路径寻找以下文件,导入到本文件
#include <map>//
#include <memory>
#include <string>
#include <utility>
#include <vector>
#include "utils/file_utils.h"//按照路径寻找以下文件,导入到本文件
#include "utils/ms_utils.h"
#include "minddata/mindrecord/include/shard_error.h"
#include "minddata/mindrecord/include/shard_page.h"
using mindspore::LogStream;//声明mindspore空间下的LogStream
using mindspore::ExceptionType::NoExceptionType;//声明mindspore空间下ExceptionType类中的NoExceptionType
using mindspore::MsLogLevel::ERROR;//声明mindspore空间下MsLogLevel类中的ERROR
namespace mindspore {//创建名为mindspore的空间
namespace mindrecord {//创建名为mindrecord的空间
//在atomic空间中创建bool型thread_status函数
std::atomic<bool> thread_status(false);
//引用ShardHeader空间中ShardHeader函数,输入三种参数调用指定函数
//对参数shard_count_、header_size_、page_size_、compression_size_进行进行参数初始化
//给index_变量赋值值为访问Index空间的数量
ShardHeader::ShardHeader() : shard_count_(0), header_size_(0), page_size_(0), compression_size_(0) {
index_ = std::make_shared<Index>();
}
//在ShardHeader空间中创建InitializeHeader函数
Status ShardHeader::InitializeHeader(const std::vector<json> &headers, bool load_dataset) {
shard_count_ = headers.size();
int shard_index = 0;
bool first = true;
//进入循环判断first是否为真若是则进行header列表的创建
for (const auto &header : headers) {
if (first) {
first = false;
RETURN_IF_NOT_OK(ParseSchema(header["schema"]));
RETURN_IF_NOT_OK(ParseIndexFields(header["index_fields"]));
RETURN_IF_NOT_OK(ParseStatistics(header["statistics"]));
ParseShardAddress(header["shard_addresses"]);
header_size_ = header["header_size"].get<uint64_t>();
page_size_ = header["page_size"].get<uint64_t>();
compression_size_ = header.contains("compression_size") ? header["compression_size"].get<uint64_t>() : 0;
}
RETURN_IF_NOT_OK(ParsePage(header["page"], shard_index, load_dataset));
shard_index++;
}
return Status::OK();
}
//在ShardHeader空间中创建CheckFileStatus函数
Status ShardHeader::CheckFileStatus(const std::string &path) {
auto realpath = FileUtils::GetRealPath(path.c_str());
//捕捉错误,并输出错误信息
CHECK_FAIL_RETURN_UNEXPECTED(
realpath.has_value(),
"Invalid file, failed to get the realpath of mindrecord files. Please check file path: " + path);
std::ifstream fin(realpath.value(), std::ios::in | std::ios::binary);
CHECK_FAIL_RETURN_UNEXPECTED(fin.is_open(),
"Invalid file, failed to open files for loading mindrecord files. Please check file "
"path, permission and open file limit: " +
path);
// fetch file size获取文件大小
auto &io_seekg = fin.seekg(0, std::ios::end);
if (!io_seekg.good() || io_seekg.fail() || io_seekg.bad()) {
fin.close();
RETURN_STATUS_UNEXPECTED("[Internal ERROR] failed to seekg file, file path: " + path);
}
//捕捉错误,并输出错误信息
size_t file_size = fin.tellg();
if (file_size < kMinFileSize) {
fin.close();
RETURN_STATUS_UNEXPECTED("Invalid file, the size of mindrecord file: " + std::to_string(file_size) +
" is smaller than the lower limit: " + std::to_string(kMinFileSize) +
".\n Please check file path: " + path +
" and use 'FileWriter' to generate valid mindrecord files.");
}
fin.close();
return Status::OK();
}
//在ShardHeader空间中创建ValidateHeader函数
Status ShardHeader::ValidateHeader(const std::string &path, std::shared_ptr<json> *header_ptr) {
RETURN_UNEXPECTED_IF_NULL(header_ptr);
RETURN_IF_NOT_OK(CheckFileStatus(path));
//
auto realpath = FileUtils::GetRealPath(path.c_str());
CHECK_FAIL_RETURN_UNEXPECTED(
realpath.has_value(),
"Invalid file, failed to get the realpath of mindrecord files. Please check file path: " + path);
// read header size读取标头大小
json json_header;
std::ifstream fin(realpath.value(), std::ios::in | std::ios::binary);
CHECK_FAIL_RETURN_UNEXPECTED(fin.is_open(),
"Invalid file, failed to open files for loading mindrecord files. Please check file "
"path, permission and open file limit: " +
path);
//判断io_rea的相关参数若符合则关闭fin并返回错误信息
uint64_t header_size = 0;
auto &io_read = fin.read(reinterpret_cast<char *>(&header_size), kInt64Len);
if (!io_read.good() || io_read.fail() || io_read.bad()) {
fin.close();
RETURN_STATUS_UNEXPECTED("[Internal ERROR] failed to read file, file path: " + path);
}
//判断header列表的大小是否大于header应有的大小
//若符合则关闭fin并返回错误信息
if (header_size > kMaxHeaderSize) {
fin.close();
RETURN_STATUS_UNEXPECTED(
"Invalid file, the size of mindrecord file header is larger than the upper limit. \nPlease use 'FileWriter' to "
"generate valid mindrecord files.");
}
// read header content读取标题内容
std::vector<uint8_t> header_content(header_size);
auto &io_read_content = fin.read(reinterpret_cast<char *>(&header_content[0]), header_size);
if (!io_read_content.good() || io_read_content.fail() || io_read_content.bad()) {
fin.close();
RETURN_STATUS_UNEXPECTED("[Internal ERROR] Failed to read file, file path: " + path);
}
fin.close();
std::string raw_header_content = std::string(header_content.begin(), header_content.end());
// parse json content解析json内容
try {
json_header = json::parse(raw_header_content);
} catch (json::parse_error &e) {
RETURN_STATUS_UNEXPECTED("[Internal ERROR] Failed to parse the metadata in JSON format in the mindrecord files: " +
std::string(e.what()));
}
*header_ptr = std::make_shared<json>(json_header);
return Status::OK();
}
//引用ShardHeader空间中BuildSingleHeader函数
//创建singleheader列表
Status ShardHeader::BuildSingleHeader(const std::string &file_path, std::shared_ptr<json> *header_ptr) {
RETURN_UNEXPECTED_IF_NULL(header_ptr);
std::shared_ptr<json> raw_header;
RETURN_IF_NOT_OK(ValidateHeader(file_path, &raw_header));
uint64_t compression_size =
raw_header->contains("compression_size") ? (*raw_header)["compression_size"].get<uint64_t>() : 0;
json header = {{"shard_addresses", (*raw_header)["shard_addresses"]},
{"header_size", (*raw_header)["header_size"]},
{"page_size", (*raw_header)["page_size"]},
{"compression_size", compression_size},
{"index_fields", (*raw_header)["index_fields"]},
{"blob_fields", (*raw_header)["schema"][0]["blob_fields"]},
{"schema", (*raw_header)["schema"][0]["schema"]},
{"version", (*raw_header)["version"]}};
*header_ptr = std::make_shared<json>(header);
return Status::OK();
}
//引用ShardHeader空间中BuildDataset函数
//创建dataset列表
Status ShardHeader::BuildDataset(const std::vector<std::string> &file_paths, bool load_dataset) {
uint32_t thread_num = std::thread::hardware_concurrency();
if (thread_num == 0) {
thread_num = kThreadNumber;
}
uint32_t work_thread_num = 0;
uint32_t shard_count = file_paths.size();
int group_num = ceil(shard_count * 1.0 / thread_num);
std::vector<std::thread> thread_set(thread_num);
std::vector<json> headers(shard_count);
for (uint32_t x = 0; x < thread_num; ++x) {
int start_num = x * group_num;
int end_num = ((x + 1) * group_num > shard_count) ? shard_count : (x + 1) * group_num;
if (start_num >= end_num) {
continue;
}
thread_set[x] =
std::thread(&ShardHeader::GetHeadersOneTask, this, start_num, end_num, std::ref(headers), file_paths);
work_thread_num++;
}
for (uint32_t x = 0; x < work_thread_num; ++x) {
thread_set[x].join();
}
if (thread_status) {
thread_status = false;
RETURN_STATUS_UNEXPECTED("[Internal ERROR] Error raised in GetHeadersOneTask function.");
}
RETURN_IF_NOT_OK(InitializeHeader(headers, load_dataset));
return Status::OK();
}
//引用ShardHeader空间中GetHeadersOneTask函数
void ShardHeader::GetHeadersOneTask(int start, int end, std::vector<json> &headers,
const vector<string> &realAddresses) {
if (thread_status || end > realAddresses.size()) {
return;
}
for (int x = start; x < end; ++x) {
std::shared_ptr<json> header;
auto status = ValidateHeader(realAddresses[x], &header);
if (status.IsError()) {
thread_status = true;
return;
}
(*header)["shard_addresses"] = realAddresses;
if (std::find(kSupportedVersion.begin(), kSupportedVersion.end(), (*header)["version"]) ==
kSupportedVersion.end()) {
MS_LOG(ERROR) << "Invalid file, the version of mindrecord files" << (*header)["version"].dump()
<< " is not supported.\nPlease use 'FileWriter' to generate valid mindrecord files.";
thread_status = true;
return;
}
headers[x] = *header;
}
}
//引用ShardHeader空间中InitByFiles函数
Status ShardHeader::InitByFiles(const std::vector<std::string> &file_paths) {
std::vector<std::string> file_names(file_paths.size());
std::transform(file_paths.begin(), file_paths.end(), file_names.begin(), [](std::string fp) -> std::string {
std::shared_ptr<std::string> fn;
return GetFileName(fp, &fn).IsOk() ? *fn : "";
});
shard_addresses_ = std::move(file_names);
shard_count_ = file_paths.size();
CHECK_FAIL_RETURN_UNEXPECTED(shard_count_ != 0 && (shard_count_ <= kMaxShardCount),
"[Internal ERROR] 'shard_count_': " + std::to_string(shard_count_) +
"is not in range (0, " + std::to_string(kMaxShardCount) + "].");
pages_.resize(shard_count_);
return Status::OK();
}
//引用ShardHeader空间中ParseIndexFields函数
//进入循环遍历index_field列表获得parsed_index_fields列表
Status ShardHeader::ParseIndexFields(const json &index_fields) {
std::vector<std::pair<uint64_t, std::string>> parsed_index_fields;
for (auto &index_field : index_fields) {
auto schema_id = index_field["schema_id"].get<uint64_t>();
std::string field_name = index_field["index_field"].get<std::string>();
std::pair<uint64_t, std::string> parsed_index_field(schema_id, field_name);
parsed_index_fields.push_back(parsed_index_field);
}
RETURN_IF_NOT_OK(AddIndexFields(parsed_index_fields));
return Status::OK();
}
//引用ShardHeader空间中ParsePage函数
Status ShardHeader::ParsePage(const json &pages, int shard_index, bool load_dataset) {
// set shard_index when load_dataset is false当load_dataset为false时设置shard_index
CHECK_FAIL_RETURN_UNEXPECTED(shard_count_ <= kMaxFileCount,
"Invalid file, the number of mindrecord files: " + std::to_string(shard_count_) +
"is not in range (0, " + std::to_string(kMaxFileCount) +
"].\nPlease use 'FileWriter' to generate fewer mindrecord files.");
//判断pages_列表是否为空若是则更改pages_列表的大小
if (pages_.empty()) {
pages_.resize(shard_count_);
}
//进入循环遍历pages_列表设置pages_列表内容
for (auto &page : pages) {
int page_id = page["page_id"];
int shard_id = page["shard_id"];
std::string page_type = page["page_type"];
int page_type_id = page["page_type_id"];
auto start_row_id = page["start_row_id"].get<uint64_t>();
auto end_row_id = page["end_row_id"].get<uint64_t>();
std::vector<std::pair<int, uint64_t>> row_group_ids(page["row_group_ids"].size());
std::transform(page["row_group_ids"].begin(), page["row_group_ids"].end(), row_group_ids.begin(),
[](json rg) { return std::make_pair(rg["id"], rg["offset"].get<uint64_t>()); });
auto page_size = page["page_size"].get<uint64_t>();
std::shared_ptr<Page> parsed_page = std::make_shared<Page>(page_id, shard_id, page_type, page_type_id, start_row_id,
end_row_id, row_group_ids, page_size);
if (load_dataset == true) {
pages_[shard_id].push_back(std::move(parsed_page));
} else {
pages_[shard_index].push_back(std::move(parsed_page));
}
}
return Status::OK();
}
//引用ShardHeader空间中ParseStatistics函数
Status ShardHeader::ParseStatistics(const json &statistics) {
//进入循环遍历statistics列表若有错误输出错误信息
for (auto &statistic : statistics) {
CHECK_FAIL_RETURN_UNEXPECTED(
statistic.find("desc") != statistic.end() && statistic.find("statistics") != statistic.end(),
"[Internal ERROR] Failed to deserialize statistics: " + statistics.dump());
std::string statistic_description = statistic["desc"].get<std::string>();
json statistic_body = statistic["statistics"];
std::shared_ptr<Statistics> parsed_statistic = Statistics::Build(statistic_description, statistic_body);
RETURN_UNEXPECTED_IF_NULL(parsed_statistic);
AddStatistic(parsed_statistic);
}
return Status::OK();
}
//引用ShardHeader空间中ParseShardAddress函数
Status ShardHeader::ParseSchema(const json &schemas) {
for (auto &schema : schemas) {
// change how we get schemaBody once design is finalized设计完成后更改获取schemaBody的方式
CHECK_FAIL_RETURN_UNEXPECTED(schema.find("desc") != schema.end() && schema.find("blob_fields") != schema.end() &&
schema.find("schema") != schema.end(),
"[Internal ERROR] Failed to deserialize schema: " + schema.dump());
std::string schema_description = schema["desc"].get<std::string>();
std::vector<std::string> blob_fields = schema["blob_fields"].get<std::vector<std::string>>();
json schema_body = schema["schema"];
std::shared_ptr<Schema> parsed_schema = Schema::Build(schema_description, schema_body);
RETURN_UNEXPECTED_IF_NULL(parsed_schema);
AddSchema(parsed_schema);
}
return Status::OK();
}
//引用ShardHeader空间中ParseShardAddress函数
//复制address列表到shard_addresses_
void ShardHeader::ParseShardAddress(const json &address) {
std::copy(address.begin(), address.end(), std::back_inserter(shard_addresses_));
}
//引用ShardHeader空间中SerializeHeader函数
std::vector<std::string> ShardHeader::SerializeHeader() {
std::vector<std::string> header;
auto index = SerializeIndexFields();
auto stats = SerializeStatistics();
auto schema = SerializeSchema();
auto pages = SerializePage();
auto address = SerializeShardAddress();
//判断shard_count_是否符合条件若符合则返回string类型
if (shard_count_ > static_cast<int>(pages.size())) {
return std::vector<string>{};
}
//判断shard_count_是否小于shard_count_最大值若是则进入循环编辑s字符串最后返回字符串信息
if (shard_count_ <= kMaxShardCount) {
for (int shardId = 0; shardId < shard_count_; shardId++) {
string s;
s += "{\"header_size\":" + std::to_string(header_size_) + ",";
s += "\"index_fields\":" + index + ",";
s += "\"page\":" + pages[shardId] + ",";
s += "\"page_size\":" + std::to_string(page_size_) + ",";
s += "\"compression_size\":" + std::to_string(compression_size_) + ",";
s += "\"schema\":" + schema + ",";
s += "\"shard_addresses\":" + address + ",";
s += "\"shard_id\":" + std::to_string(shardId) + ",";
s += "\"statistics\":" + stats + ",";
s += "\"version\":\"" + std::string(kVersion) + "\"";
s += "}";
header.emplace_back(s);
}
}
return header;
}
//引用ShardHeader空间中SerializeIndexFields函数
//遍历fields列表返回schema_id、index_field的值
std::string ShardHeader::SerializeIndexFields() {
json j;
auto fields = index_->GetFields();
(void)std::transform(fields.begin(), fields.end(), std::back_inserter(j),
[](const std::pair<uint64_t, std::string> &field) -> json {
return {{"schema_id", field.first}, {"index_field", field.second}};
});
return j.dump();
}
//引用ShardHeader空间中SerializePage函数
//遍历shard_pages列表返回GetPage函数的值
std::vector<std::string> ShardHeader::SerializePage() {
std::vector<string> pages;
for (auto &shard_pages : pages_) {
json j;
(void)std::transform(shard_pages.begin(), shard_pages.end(), std::back_inserter(j),
[](const std::shared_ptr<Page> &p) { return p->GetPage(); });
pages.emplace_back(j.dump());
}
return pages;
}
//引用ShardHeader空间中SerializeStatistics函数
//遍历statistics_列表返回GetStatistics函数的值
std::string ShardHeader::SerializeStatistics() {
json j;
(void)std::transform(statistics_.begin(), statistics_.end(), std::back_inserter(j),
[](const std::shared_ptr<Statistics> &stats) { return stats->GetStatistics(); });
return j.dump();
}
//引用ShardHeader空间中SerializeSchema函数
//遍历schema_列表返回GetSchema函数的值
std::string ShardHeader::SerializeSchema() {
json j;
(void)std::transform(schema_.begin(), schema_.end(), std::back_inserter(j),
[](const std::shared_ptr<Schema> &schema) { return schema->GetSchema(); });
return j.dump();
}
//引用ShardHeader空间中SerializeShardAddress函数
//进入循环,一次根据地址获得文件名并判断是否为空
std::string ShardHeader::SerializeShardAddress() {
json j;
std::shared_ptr<std::string> fn_ptr;
for (const auto &addr : shard_addresses_) {
(void)GetFileName(addr, &fn_ptr);
(void)j.emplace_back(*fn_ptr);
}
return j.dump();
}
//引用ShardHeader空间中GetPage函数
//判断shard_id、page_id是否在标准范围内若是则获取pages_列表中的对应信息若不是则返回错误信息
Status ShardHeader::GetPage(const int &shard_id, const int &page_id, std::shared_ptr<Page> *page_ptr) {
RETURN_UNEXPECTED_IF_NULL(page_ptr);
if (shard_id < static_cast<int>(pages_.size()) && page_id < static_cast<int>(pages_[shard_id].size())) {
*page_ptr = pages_[shard_id][page_id];
return Status::OK();
}
page_ptr = nullptr;
RETURN_STATUS_UNEXPECTED("[Internal ERROR] Failed to get Page, 'page_id': " + std::to_string(page_id));
}
//引用ShardHeader空间中SetPage函数
//判断shard_id、page_id是否在标准范围内若是则在pages_列表中加入新值若不是则返回错误信息
Status ShardHeader::SetPage(const std::shared_ptr<Page> &new_page) {
int shard_id = new_page->GetShardID();
int page_id = new_page->GetPageID();
if (shard_id < static_cast<int>(pages_.size()) && page_id < static_cast<int>(pages_[shard_id].size())) {
pages_[shard_id][page_id] = new_page;
return Status::OK();
}
RETURN_STATUS_UNEXPECTED("[Internal ERROR] Failed to set Page, 'page_id': " + std::to_string(page_id));
}
//引用ShardHeader空间中AddPage函数
//判断shard_id、page_id是否在标准范围内若是则在pages_列表中添加page若不是则返回错误信息
Status ShardHeader::AddPage(const std::shared_ptr<Page> &new_page) {
int shard_id = new_page->GetShardID();
int page_id = new_page->GetPageID();
if (shard_id < static_cast<int>(pages_.size()) && page_id == static_cast<int>(pages_[shard_id].size())) {
pages_[shard_id].push_back(new_page);
return Status::OK();
}
RETURN_STATUS_UNEXPECTED("[Internal ERROR] Failed to add Page, 'page_id': " + std::to_string(page_id));
}
//引用ShardHeader空间中GetLastPageId函数
//判断shard_id是否在范围内若是则返回0若不是则返回pages_列表的大小-1的值
int64_t ShardHeader::GetLastPageId(const int &shard_id) {
if (shard_id >= static_cast<int>(pages_.size())) {
return 0;
}
return pages_[shard_id].size() - 1;
}
//引用ShardHeader空间中GetLastPageIdByType函数
int ShardHeader::GetLastPageIdByType(const int &shard_id, const std::string &page_type) {
//判断shard_id是否在范围内若是则返回0
if (shard_id >= static_cast<int>(pages_.size())) {
return 0;
}
int last_page_id = -1;
//进入循环若pages_列表中存在page_type则给last_page_id 赋值
for (uint64_t i = pages_[shard_id].size(); i >= 1; i--) {
if (pages_[shard_id][i - 1]->GetPageType() == page_type) {
last_page_id = pages_[shard_id][i - 1]->GetPageID();
return last_page_id;
}
}
return last_page_id;
}
//引用ShardHeader空间中GetPageByGroupId函数
//若发现错误则输出错误信息
//进入循环建立page_ptr链表
Status ShardHeader::GetPageByGroupId(const int &group_id, const int &shard_id, std::shared_ptr<Page> *page_ptr) {
RETURN_UNEXPECTED_IF_NULL(page_ptr);
CHECK_FAIL_RETURN_UNEXPECTED(shard_id < static_cast<int>(pages_.size()),
"[Internal ERROR] 'shard_id': " + std::to_string(shard_id) +
" should be smaller than the size of 'pages_': " + std::to_string(pages_.size()) +
".");
for (uint64_t i = pages_[shard_id].size(); i >= 1; i--) {
auto page = pages_[shard_id][i - 1];
if (page->GetPageType() == kPageTypeBlob && page->GetPageTypeID() == group_id) {
*page_ptr = std::make_shared<Page>(*page);
return Status::OK();
}
}
page_ptr = nullptr;
RETURN_STATUS_UNEXPECTED("[Internal ERROR] Failed to get Page, 'group_id': " + std::to_string(group_id));
}
//引用ShardHeader空间中AddSchema函数
int ShardHeader::AddSchema(std::shared_ptr<Schema> schema) {
//判断schema列表是否为空若是则返回错误信息
if (schema == nullptr) {
MS_LOG(ERROR) << "[Internal ERROR] The pointer of schema is NULL.";
return -1;
}
//继续判断schema空间中的存储空间是否为空若是则返回错误信息
if (!schema_.empty()) {
MS_LOG(ERROR) << "The schema is added repeatedly. Please remove the redundant 'add_schema' function.";
return -1;
}
//判断schema_id是否为-1若是则给schema_id再赋值后加入到schema列表
int64_t schema_id = schema->GetSchemaID();
if (schema_id == -1) {
schema_id = schema_.size();
schema->SetSchemaID(schema_id);
}
schema_.push_back(schema);
return schema_id;
}
//引用ShardHeader空间中AddStatistic函数
//判断statistic是否为真若是则对statistic_id赋值并将值列入statistic列表
void ShardHeader::AddStatistic(std::shared_ptr<Statistics> statistic) {
if (statistic) {
int64_t statistics_id = statistic->GetStatisticsID();
if (statistics_id == -1) {
statistics_id = statistics_.size();
statistic->SetStatisticsID(statistics_id);
}
statistics_.push_back(statistic);
}
}
//引用ShardHeader空间中InitIndexPtr函数
//判断index_是否为真若是则进行操作
std::shared_ptr<Index> ShardHeader::InitIndexPtr() {
std::shared_ptr<Index> index = index_;
if (!index_) {
index = std::make_shared<Index>();
index_ = index;
}
return index;
}
//引用ShardHeader空间中CheckIndexField函数,输入参数n调用指定函数
Status ShardHeader::CheckIndexField(const std::string &field, const json &schema) {
// check field name is or is not valid检查字段名称无效
CHECK_FAIL_RETURN_UNEXPECTED(schema.find(field) != schema.end(),
"Invalid input, 'index_fields': " + field + " can not found in schema: " +
schema.dump() + ".\n Please use 'add_index' function to add proper 'index_fields'.");
CHECK_FAIL_RETURN_UNEXPECTED(schema[field]["type"] != "Bytes",
"Invalid input, type of 'index_fields': " + field +
" is bytes and can not set as an 'index_fields'.\n Please use 'add_index' function to "
"add the other 'index_fields'.");
CHECK_FAIL_RETURN_UNEXPECTED(schema.find(field) == schema.end() || schema[field].find("shape") == schema[field].end(),
"Invalid input, type of 'index_fields': " + field +
" is array and can not set as an 'index_fields'.\n Please use 'add_index' function to "
"add the other 'index_fields'.");
return Status::OK();
}
//引用ShardHeader空间中AddIndexFields函数,输入参数n调用指定函数
Status ShardHeader::AddIndexFields(const std::vector<std::string> &fields) {
//判断fields是否为空
if (fields.empty()) {
return Status::OK();
}
CHECK_FAIL_RETURN_UNEXPECTED(!GetSchemas().empty(),
"Invalid data, schema is empty. Please use 'add_schema' function to add schema first.");
// create index Object创建索引对象
std::shared_ptr<Index> index = InitIndexPtr();
for (const auto &schemaPtr : schema_) {
std::shared_ptr<Schema> schema_ptr;
RETURN_IF_NOT_OK(GetSchemaByID(schemaPtr->GetSchemaID(), &schema_ptr));
json schema = schema_ptr->GetSchema().at("schema");
// checkout and add fields for each schema签出并为每个架构添加字段
std::set<std::string> field_set;
for (const auto &item : index->GetFields()) {
field_set.insert(item.second);
}
for (const auto &field : fields) {
CHECK_FAIL_RETURN_UNEXPECTED(
field_set.find(field) == field_set.end(),
"The 'index_fields': " + field + " is added repeatedly. Please remove the redundant 'add_index' function.");
// check field name is or is not valid检查字段名称无效
RETURN_IF_NOT_OK(CheckIndexField(field, schema));
field_set.insert(field);
// add field into index将字段添加到索引中
index.get()->AddIndexField(schemaPtr->GetSchemaID(), field);
}
}
index_ = index;
return Status::OK();
}
//引用ShardHeader空间中GetAllSchemaID函数,输入参数n调用指定函数
Status ShardHeader::GetAllSchemaID(std::set<uint64_t> &bucket_count) {
// get all schema id获取所有架构id
for (const auto &schema : schema_) {
auto schema_id = schema->GetSchemaID();
CHECK_FAIL_RETURN_UNEXPECTED(bucket_count.find(schema_id) == bucket_count.end(),
"[Internal ERROR] duplicate schema exist, schema id: " + std::to_string(schema_id));
bucket_count.insert(schema_id);
}
return Status::OK();
}
//引用ShardHeader空间中AddIndexFields函数,输入参数n调用指定函数
Status ShardHeader::AddIndexFields(std::vector<std::pair<uint64_t, std::string>> fields) {
//判断fields是否为空
if (fields.empty()) {
return Status::OK();
}
// create index Object创建索引对象
std::shared_ptr<Index> index = InitIndexPtr();
// get all schema id获取所有架构id
std::set<uint64_t> bucket_count;
RETURN_IF_NOT_OK(GetAllSchemaID(bucket_count));
// check and add fields for each schema检查并添加每个模式的字段
std::set<std::pair<uint64_t, std::string>> field_set;
for (const auto &item : index->GetFields()) {
field_set.insert(item);
}
for (const auto &field : fields) {
CHECK_FAIL_RETURN_UNEXPECTED(field_set.find(field) == field_set.end(),
"The 'index_fields': " + field.second +
" is added repeatedly. Please remove the redundant 'add_index' function.");
uint64_t schema_id = field.first;
std::string field_name = field.second;
// check schemaId is or is not valid check schemaId无效
CHECK_FAIL_RETURN_UNEXPECTED(bucket_count.find(schema_id) != bucket_count.end(),
"[Internal ERROR] 'schema_id': " + std::to_string(schema_id) + " can not found.");
// check field name is or is not valid check field name无效
std::shared_ptr<Schema> schema_ptr;
RETURN_IF_NOT_OK(GetSchemaByID(schema_id, &schema_ptr));
json schema = schema_ptr->GetSchema().at("schema");
CHECK_FAIL_RETURN_UNEXPECTED(schema.find(field_name) != schema.end(),
"Invalid input, 'index_fields': " + field_name + " can not found in schema: " +
schema.dump() + ".\n Please use 'add_index' function to add proper 'index_fields'.");
RETURN_IF_NOT_OK(CheckIndexField(field_name, schema));
field_set.insert(field);
// add field into index将字段添加到索引中
index->AddIndexField(schema_id, field_name);
}
index_ = index;
return Status::OK();
}
//引用ShardHeader空间中GetShardAddressByID函数,输入参数n调用指定函数
//判断shard_id是否大于shard_addresses_列表的大小若是则返回“”若不是则返回shard_addresses_列表中at函数的返回值
std::string ShardHeader::GetShardAddressByID(int64_t shard_id) {
if (shard_id >= shard_addresses_.size()) {
return "";
}
return shard_addresses_.at(shard_id);
}
//引用ShardHeader空间中GetSchemas函数,返回schema_的值
std::vector<std::shared_ptr<Schema>> ShardHeader::GetSchemas() { return schema_; }
//引用ShardHeader空间中GetStatistics函数,返回statistics_的值
std::vector<std::shared_ptr<Statistics>> ShardHeader::GetStatistics() { return statistics_; }
//引用ShardHeader空间中GetFields函数,返回index_中GetFields的函数返回值
std::vector<std::pair<uint64_t, std::string>> ShardHeader::GetFields() { return index_->GetFields(); }
//引用ShardHeader空间中GetIndex函数,返回index_的值
std::shared_ptr<Index> ShardHeader::GetIndex() { return index_; }
//引用ShardHeader空间中GetSchemaByID函数
//判断schema列表中id是否在标准范围内
Status ShardHeader::GetSchemaByID(int64_t schema_id, std::shared_ptr<Schema> *schema_ptr) {
RETURN_UNEXPECTED_IF_NULL(schema_ptr);
int64_t schema_size = schema_.size();
CHECK_FAIL_RETURN_UNEXPECTED(schema_id >= 0 && schema_id < schema_size,
"[Internal ERROR] 'schema_id': " + std::to_string(schema_id) + " is not in range [0, " +
std::to_string(schema_size) + ").");
*schema_ptr = schema_.at(schema_id);
return Status::OK();
}
//引用ShardHeader空间中GetStatisticByID函数
//判断statistic列表中id的值是否在标准范围内
Status ShardHeader::GetStatisticByID(int64_t statistic_id, std::shared_ptr<Statistics> *statistics_ptr) {
RETURN_UNEXPECTED_IF_NULL(statistics_ptr);
int64_t statistics_size = statistics_.size();
CHECK_FAIL_RETURN_UNEXPECTED(statistic_id >= 0 && statistic_id < statistics_size,
"[Internal ERROR] 'statistic_id': " + std::to_string(statistic_id) +
" is not in range [0, " + std::to_string(statistics_size) + ").");
*statistics_ptr = statistics_.at(statistic_id);
return Status::OK();
}
//在ShardHeader空间中创建PagesToFile函数
Status ShardHeader::PagesToFile(const std::string dump_file_name) {
auto realpath = FileUtils::GetRealPath(dump_file_name.c_str());
CHECK_FAIL_RETURN_UNEXPECTED(realpath.has_value(),
"[Internal ERROR] Failed to get the realpath of Pages file, path: " + dump_file_name);
// write header content to file, dump whatever is in the file before将头内容写入文件转储之前文件中的任何内容
std::ofstream page_out_handle(realpath.value(), std::ios_base::trunc | std::ios_base::out);
CHECK_FAIL_RETURN_UNEXPECTED(page_out_handle.good(),
"[Internal ERROR] Failed to open Pages file, path: " + dump_file_name);
auto pages = SerializePage();
for (const auto &shard_pages : pages) {
page_out_handle << shard_pages << "\n";
}
page_out_handle.close();
return Status::OK();
}
//在ShardHeader空间中创建FileToPages函数
Status ShardHeader::FileToPages(const std::string dump_file_name) {
for (auto &v : pages_) { // clean pages清理页面
v.clear();
}
auto realpath = FileUtils::GetRealPath(dump_file_name.c_str());
CHECK_FAIL_RETURN_UNEXPECTED(realpath.has_value(),
"[Internal ERROR] Failed to get the realpath of Pages file, path: " + dump_file_name);
// attempt to open the file contains the page in json试图打开包含json页面的文件
std::ifstream page_in_handle(realpath.value());
CHECK_FAIL_RETURN_UNEXPECTED(page_in_handle.good(),
"[Internal ERROR] Pages file does not exist, path: " + dump_file_name);
std::string line;
while (std::getline(page_in_handle, line)) {
RETURN_IF_NOT_OK(ParsePage(json::parse(line), -1, true));
}
page_in_handle.close();
return Status::OK();
}
//在ShardHeader空间中创建Initialize函数
Status ShardHeader::Initialize(const std::shared_ptr<ShardHeader> *header_ptr, const json &schema,
const std::vector<std::string> &index_fields, std::vector<std::string> &blob_fields,
uint64_t &schema_id) {
RETURN_UNEXPECTED_IF_NULL(header_ptr);
auto schema_ptr = Schema::Build("mindrecord", schema);
CHECK_FAIL_RETURN_UNEXPECTED(schema_ptr != nullptr, "[Internal ERROR] Failed to build schema: " + schema.dump() +
"." + "Check the [ERROR] logs before for more details.");
schema_id = (*header_ptr)->AddSchema(schema_ptr);
// create index创建索引
std::vector<std::pair<uint64_t, std::string>> id_index_fields;
if (!index_fields.empty()) {
(void)transform(index_fields.begin(), index_fields.end(), std::back_inserter(id_index_fields),
[schema_id](const std::string &el) { return std::make_pair(schema_id, el); });
RETURN_IF_NOT_OK((*header_ptr)->AddIndexFields(id_index_fields));
}
auto build_schema_ptr = (*header_ptr)->GetSchemas()[0];
blob_fields = build_schema_ptr->GetBlobFields();
return Status::OK();
}
} // namespace mindrecord
} // namespace mindspore