源码路径
curve-release2.2\src\chunkserver\raftsnapshot
1. `curve_snapshot_writer.cpp`
2. `curve_file_service.cpp`
3. `curve_snapshot_file_reader.cpp`
4. `curve_snapshot_copier.cpp`
5. `curve_filesystem_adaptor.cpp`
6. `curve_snapshot_attachment.cpp`
7. `curve_snapshot.cpp`
8. `curve_snapshot_reader.cpp`
9. `curve_snapshot_storage.cpp`
以下是对curve_snapshot_writer.cpp
文件中源码的详细分析,我将在代码中添加注释以解释每一部分的功能和作用。
/*
* Copyright (c) 2020 NetEase Inc.
* 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 "src/chunkserver/raftsnapshot/curve_snapshot_writer.h"
// 命名空间声明
namespace curve {
namespace chunkserver {
// CurveSnapshotWriter类的构造函数
CurveSnapshotWriter::CurveSnapshotWriter(const std::string& path,
braft::FileSystemAdaptor* fs)
: _path(path), _fs(fs) {
// 初始化成员变量_path和_fs
}
// CurveSnapshotWriter类的析构函数
CurveSnapshotWriter::~CurveSnapshotWriter() {
// 清理资源
}
// 初始化方法,准备快照写入所需的环境
int CurveSnapshotWriter::init() {
butil::File::Error e;
if (!_fs->create_directory(_path, &e, false)) { // 创建快照目录
set_error(EIO, "CreateDirectory failed, path: %s", _path.c_str());
return EIO;
}
std::string meta_path = _path + "/" BRAFT_SNAPSHOT_META_FILE; // 构造元数据文件路径
if (_fs->path_exists(meta_path) &&
_meta_table.load_from_file(_fs, meta_path) != 0) { // 加载元数据表
set_error(EIO, "Fail to load metatable from %s", meta_path.c_str());
return EIO;
}
// 清理不一致的文件
std::vector<std::string> to_remove;
braft::DirReader* dir_reader = _fs->directory_reader(_path);
if (!dir_reader->is_valid()) { // 检查目录读取器是否有效
LOG(WARNING) << "directory reader failed, maybe NOEXIST or"
<< " PERMISSION, path: " << _path;
delete dir_reader;
return EIO;
}
while (dir_reader->next()) { // 遍历目录中的文件
std::string filename = dir_reader->name();
if (filename != BRAFT_SNAPSHOT_META_FILE) {
if (get_file_meta(filename, NULL) != 0) { // 获取文件元数据
to_remove.push_back(filename); // 标记需要删除的文件
}
}
}
delete dir_reader;
for (size_t i = 0; i < to_remove.size(); ++i) { // 删除标记的文件
std::string file_path = _path + "/" + to_remove[i];
_fs->delete_file(file_path, false);
LOG(WARNING) << "Snapshot file exist but meta not found so"
<< " delete it, path: " << file_path;
}
return 0; // 初始化成功
}
// 获取快照的索引
int64_t CurveSnapshotWriter::snapshot_index() {
return _meta_table.has_meta() ?
_meta_table.meta().last_included_index() : 0;
}
// 从元数据表中移除文件记录
int CurveSnapshotWriter::remove_file(const std::string& filename) {
return _meta_table.remove_file(filename);
}
// 向元数据表中添加文件记录
int CurveSnapshotWriter::add_file(
const std::string& filename,
const ::google::protobuf::Message* file_meta) {
braft::LocalFileMeta meta;
if (file_meta) {
meta.CopyFrom(*file_meta); // 从给定的文件元数据中复制信息
}
return _meta_table.add_file(filename, meta); // 添加文件记录到元数据表
}
// 列出所有文件
void CurveSnapshotWriter::list_files(std::vector<std::string> *files) {
return _meta_table.list_files(files); // 调用元数据表的list_files方法
}
// 获取特定文件的元数据
int CurveSnapshotWriter::get_file_meta(const std::string& filename,
::google::protobuf::Message* file_meta) {
braft::LocalFileMeta* meta = NULL;
if (file_meta) {
meta = dynamic_cast<braft::LocalFileMeta*>(file_meta); // 转换文件元数据类型
if (meta == NULL) {
return -1;
}
}
return _meta_table.get_file_meta(filename, meta); // 从元数据表中获取文件元数据
}
// 保存快照元数据到文件
int CurveSnapshotWriter::save_meta(const braft::SnapshotMeta& meta) {
_meta_table.set_meta(meta); // 设置元数据表的快照元数据
return 0; // 成功
}
// 同步元数据到文件系统
int CurveSnapshotWriter::sync() {
const int rc = _meta_table.save_to_file(
_fs, _path + "/" BRAFT_SNAPSHOT_META_FILE); // 保存元数据到文件
if (rc != 0 && ok()) { // 检查返回代码和错误状态
LOG(ERROR) << "Fail to sync, path: " << _path;
set_error(rc, "Fail to sync : %s", berror(rc));
}
return rc; // 返回操作结果
}
} // namespace chunkserver
} // namespace curve
这段代码定义了一个CurveSnapshotWriter
类,它负责创建和管理快照文件。类中包含了构造函数、析构函数、初始化方法、获取快照索引的方法、文件操作相关的方法(添加、移除、列出文件和获取文件元数据),以及同步元数据的方法。
在初始化方法init
中,首先尝试创建一个快照目录,然后加载已有的元数据表。如果加载成功,它会检查目录中的每个文件,移除那些在元数据表中没有记录的文件。
snapshot_index
方法返回当前快照的索引,这个索引是所有已包含在快照中的日志条目的最大索引。
remove_file
和add_file
方法用于操作元数据表中的文件记录,分别用于从快照中移除文件和向快照中添加文件。
list_files
和get_file_meta
方法提供了查询快照中文件列表和获取特定文件元数据的功能。
save_meta
方法用于保存快照的元数据到内存中的元数据表。
sync
方法将内存中的元数据同步到文件系统中,确保数据的持久化。
整体来说,这个类的目的是为分布式存储系统中的快照功能提供文件级别的管理和持久化机制。
以下是对curve_file_service.cpp
文件中源码的详细分析,我将在代码中添加注释以解释每一部分的功能和作用。
/*
* Copyright (c) 2020 NetEase Inc.
* 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 "src/chunkserver/raftsnapshot/curve_file_service.h"
// 命名空间声明
namespace curve {
namespace chunkserver {
// 定义全局的CurveFileService实例,通过GetInstance()方法可以获取到这个实例
CurveFileService& kCurveFileService = CurveFileService::GetInstance();
// 'get_file'方法用于获取文件内容,它是RPC调用的一部分
void CurveFileService::get_file(::google::protobuf::RpcController* controller,
const ::braft::GetFileRequest* request,
::braft::GetFileResponse* response,
::google::protobuf::Closure* done) {
// 创建一个文件读取器
scoped_refptr<braft::FileReader> reader;
brpc::ClosureGuard done_guard(done); // 确保在完成时调用done回调
brpc::Controller* cntl = (brpc::Controller*)controller; // 转换控制器类型
std::unique_lock<braft::raft_mutex_t> lck(_mutex); // 加锁以保证线程安全
Map::const_iterator iter = _reader_map.find(request->reader_id()); // 查找文件读取器
if (iter == _reader_map.end()) { // 如果找不到对应的读取器
lck.unlock(); // 解锁
cntl->SetFailed(ENXIO, "Fail to find reader=%" PRId64, request->reader_id()); // 设置错误信息
return;
}
reader = iter->second; // 获取文件读取器
lck.unlock(); // 解锁
// 检查请求的有效性
if (request->count() <= 0 || request->offset() < 0) {
cntl->SetFailed(brpc::EREQUEST, "Invalid request=%s", request->ShortDebugString().c_str());
return;
}
butil::IOBuf buf; // 创建一个IO缓冲区用于读取文件数据
bool is_eof = false; // 标记文件是否结束
size_t read_count = 0; // 读取的字节数
// 如果请求的是快照附件的元数据文件
if (request->filename() == BRAFT_SNAPSHOT_ATTACH_META_FILE) {
// 检查是否有快照附件
bool snapshotAttachmentExist = false;
{
std::unique_lock<braft::raft_mutex_t> lck(_mutex);
if (nullptr == _snapshot_attachment.get()) {
LOG(WARNING) << "_snapshot_attachment not set";
is_eof = true;
read_count = 0;
} else {
snapshotAttachmentExist = true;
}
}
if (snapshotAttachmentExist) {
// 获取快照附件文件列表
std::vector<std::string> files;
_snapshot_attachment->list_attach_files(&files, reader->path());
CurveSnapshotAttachMetaTable attachMetaTable; // 创建附件元数据表
for (size_t i = 0; i < files.size(); ++i) {
LocalFileMeta meta;
attachMetaTable.add_attach_file(files[i], meta); // 添加文件到元数据表
}
// 将附件元数据表序列化为IO缓冲区
if (attachMetaTable.save_to_iobuf_as_remote(&buf) != 0) {
LOG(ERROR) << "Fail to serialize LocalSnapshotAttachMetaTable as iobuf";
cntl->SetFailed(brpc::EINTERNAL, "serialize snapshot attach meta table fail");
return;
} else {
LOG(INFO) << "LocalSnapshotAttachMetaTable encode buf length = " << buf.size();
}
is_eof = true; // 文件结束
read_count = buf.size(); // 设置读取的字节数
}
} else {
// 如果请求的是其他文件,则继续使用raft的文件下载流程
const int rc = reader->read_file(&buf, request->filename(),
request->offset(), request->count(),
request->read_partly(),
&read_count, &is_eof); // 读取文件内容
if (rc != 0) {
cntl->SetFailed(rc, "Fail to read from path=%s filename=%s : %s",
reader->path().c_str(),
request->filename().c_str(), berror(rc));
return;
}
}
response->set_eof(is_eof); // 设置文件结束标记
response->set_read_size(read_count); // 设置读取的字节数
// 跳过空数据
if (buf.size() == 0) {
return;
}
braft::FileSegData seg_data; // 创建文件段数据结构
seg_data.append(buf, request->offset()); // 将数据追加到文件段
cntl->response_attachment().swap(seg_data.data()); // 将数据交换到响应的附件中
}
// 设置快照附件
void CurveFileService::set_snapshot_attachment(SnapshotAttachment *snapshot_attachment) {
_snapshot_attachment = snapshot_attachment;
}
// CurveFileService类的构造函数
CurveFileService::CurveFileService() {
_next_id = ((int64_t)getpid() << 45) | (butil::gettimeofday_us() >> 17); // 初始化下一个可用的reader_id
}
// 添加文件读取器
int CurveFileService::add_reader(braft::FileReader* reader, int64_t* reader_id) {
BAIDU_SCOPED_LOCK(_mutex); // 加锁
*reader_id = _next_id++; // 分配新的reader_id
_reader_map[*reader_id] = reader; // 将读取器添加到映射中
return 0; // 添加成功
}
// 移除文件读取器
int CurveFileService::remove_reader(int64_t reader_id) {
BAIDU_SCOPED_LOCK(_mutex); // 加锁
return _reader_map.erase(reader_id) == 1 ? 0 : -1; // 尝试移除读取器,返回操作结果
}
} // namespace chunkserver
} // namespace curve
这段代码定义了一个CurveFileService
类,它负责处理文件的读取请求,特别是与快照附件相关的请求。类中包含了构造函数、添加和移除文件读取器的方法,以及处理文件读取请求的方法get_file
。
在get_file
方法中,首先检查请求的文件是否是快照附件的元数据文件。如果是,它会检查是否有快照附件存在,如果存在,则获取附件文件列表,并将其序列化为IO缓冲区,然后将其作为响应的一部分发送给请求者。如果请求的是其他文件,它会调用FileReader
的read_file
方法来读取文件内容。
set_snapshot_attachment
方法用于设置快照附件,这通常在处理快照时使用。
add_reader
方法用于添加一个新的文件读取器到服务中,并为其分配一个唯一的ID。remove_reader
方法则用于移除一个文件读取器。
整体来说,这个类提供了一个服务,用于处理分布式系统中的文件读取请求,特别是那些与快照相关的请求。它通过维护一个文件读取器的映射来管理文件的读取操作,并提供了一种机制来处理快照附件的元数据。
以下是对curve_snapshot_file_reader.cpp
文件中源码的详细分析,我将在代码中添加注释以解释每一部分的功能和作用。
/*
* Copyright (c) 2020 NetEase Inc.
* 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 "src/chunkserver/raftsnapshot/curve_snapshot_file_reader.h"
#include "src/chunkserver/raftsnapshot/curve_file_service.h"
// 命名空间声明
namespace curve {
namespace chunkserver {
// 定义CurveSnapshotAttachMetaTable类的构造函数
CurveSnapshotAttachMetaTable::CurveSnapshotAttachMetaTable() {}
// 定义CurveSnapshotAttachMetaTable类的析构函数
CurveSnapshotAttachMetaTable::~CurveSnapshotAttachMetaTable() {}
// 向元数据表中添加附件文件
int CurveSnapshotAttachMetaTable::add_attach_file(const std::string& filename,
const LocalFileMeta& meta) {
Map::value_type value(filename, meta); // 创建键值对
std::pair<Map::iterator, bool> ret = _file_map.insert(value); // 插入到文件映射中
LOG_IF(WARNING, !ret.second) << "attach file=" << filename
<< " already exists in snapshot"; // 如果文件已存在,则记录警告
return ret.second ? 0 : -1; // 返回插入结果
}
// 从IO缓冲区中加载远程附件元数据表
int CurveSnapshotAttachMetaTable::load_from_iobuf_as_remote(const butil::IOBuf& buf) {
CurveSnapshotPbAttachMeta pb_attach_meta; // 创建协议缓冲区对象
butil::IOBufAsZeroCopyInputStream wrapper(buf); // 创建输入流包装器
if (!pb_attach_meta.ParseFromZeroCopyStream(&wrapper)) { // 解析协议缓冲区数据
LOG(ERROR) << "Fail to parse LocalSnapshotPbMeta";
return -1;
}
_file_map.clear(); // 清空当前映射
for (int i = 0; i < pb_attach_meta.files_size(); ++i) { // 遍历文件列表
const CurveSnapshotPbAttachMeta::File& f = pb_attach_meta.files(i);
_file_map[f.name()] = f.meta(); // 将文件添加到映射中
}
return 0; // 加载成功
}
// 将附件元数据表序列化为IO缓冲区以供远程传输
int CurveSnapshotAttachMetaTable::save_to_iobuf_as_remote(butil::IOBuf* buf) const {
CurveSnapshotPbAttachMeta pb_attach_meta; // 创建协议缓冲区对象
for (Map::const_iterator iter = _file_map.begin(); iter != _file_map.end(); ++iter) {
CurveSnapshotPbAttachMeta::File* f = pb_attach_meta.add_files(); // 添加文件到协议缓冲区
f->set_name(iter->first); // 设置文件名
*f->mutable_meta() = iter->second; // 设置文件元数据
f->mutable_meta()->clear_source(); // 清除源信息
}
buf->clear(); // 清空输出缓冲区
butil::IOBufAsZeroCopyOutputStream wrapper(buf); // 创建输出流包装器
return pb_attach_meta.SerializeToZeroCopyStream(&wrapper) ? 0 : -1; // 序列化到输出缓冲区
}
// 列出所有附件文件
void CurveSnapshotAttachMetaTable::list_files(std::vector<std::string>* files) const {
if (!files) { // 检查输出向量是否为空
return;
}
files->clear(); // 清空输出向量
files->reserve(_file_map.size()); // 预分配空间
for (Map::const_iterator iter = _file_map.begin(); iter != _file_map.end(); ++iter) {
files->push_back(iter->first); // 添加文件名到输出向量
}
}
// 获取特定附件文件的元数据
int CurveSnapshotAttachMetaTable::get_attach_file_meta(const std::string& filename,
braft::LocalFileMeta* file_meta) const {
Map::const_iterator iter = _file_map.find(filename); // 查找文件映射
if (iter == _file_map.end()) { // 如果找不到文件
return -1;
}
if (file_meta) { // 如果需要返回文件元数据
LocalFileMeta meta = iter->second; // 获取文件元数据
file_meta->set_user_meta(meta.user_meta()); // 设置用户元数据
file_meta->set_checksum(meta.checksum()); // 设置校验和
if (meta.source() == FILE_SOURCE_LOCAL) {
file_meta->set_source(braft::FILE_SOURCE_LOCAL); // 设置文件来源
} else {
file_meta->set_source(braft::FILE_SOURCE_REFERENCE); // 设置文件来源
}
}
return 0; // 成功
}
// 定义CurveSnapshotFileReader类的构造函数
CurveSnapshotFileReader::CurveSnapshotFileReader() {}
// 定义CurveSnapshotFileReader类的析构函数
CurveSnapshotFileReader::~CurveSnapshotFileReader() {
destroy_reader_in_file_service(); // 销毁文件服务中的读取器
}
// 初始化CurveSnapshotFileReader
int CurveSnapshotFileReader::init() {
// 省略具体实现,初始化方法通常涉及资源的分配和配置
}
// 从文件中读取内容
int CurveSnapshotFileReader::read_file(butil::IOBuf* out,
const std::string& filename,
off_t offset,
size_t max_count,
bool read_partly,
size_t* read_count,
bool* is_eof) const {
// 省略具体实现,read_file方法通常涉及文件I/O操作
}
} // namespace chunkserver
} // namespace curve
这段代码定义了CurveSnapshotAttachMetaTable
和CurveSnapshotFileReader
两个类,它们都是与快照文件读取相关的组件。
CurveSnapshotAttachMetaTable
类用于管理快照附件文件的元数据。它提供了添加、加载、序列化和列出附件文件的方法,以及获取特定文件的元数据。这个类使用一个映射(_file_map
)来存储文件名和元数据的键值对。
CurveSnapshotFileReader
类提供了文件读取的功能。它有一个析构函数来确保资源被正确释放,以及一个init
方法来进行初始化。read_file
方法用于从快照文件中读取指定范围的内容。
请注意,这段代码中的某些实现细节被省略了,例如init
和read_file
方法的具体实现。这些方法的具体实现将依赖于底层的文件系统和快照存储机制。
以下是对curve_snapshot_copier.cpp
文件中源码的详细分析,我将在代码中添加注释以解释每一部分的功能和作用。
/*
* Copyright (c) 2020 NetEase Inc.
* 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 "src/chunkserver/raftsnapshot/curve_snapshot_copier.h"
// 命名空间声明
namespace curve {
namespace chunkserver {
// 构造CurveSnapshotCopier对象
CurveSnapshotCopier::CurveSnapshotCopier(CurveSnapshotStorage* storage,
bool filter_before_copy_remote,
braft::FileSystemAdaptor* fs,
braft::SnapshotThrottle* throttle)
: _tid(INVALID_BTHREAD), // 初始化线程ID为无效
_cancelled(false), // 初始化取消标志为false
_filter_before_copy_remote(filter_before_copy_remote), // 是否在复制前过滤远程快照
_fs(fs), // 文件系统适配器
_throttle(throttle), // 快照节流对象
_writer(NULL), // 快照写入器
_storage(storage), // 快照存储对象
_reader(NULL), // 快照读取器
_cur_session(NULL) // 当前会话对象
{
// 构造函数内容
}
// 析构CurveSnapshotCopier对象
CurveSnapshotCopier::~CurveSnapshotCopier() {
CHECK(!_writer); // 检查写入器是否已被释放
}
// 启动复制快照的线程
void* CurveSnapshotCopier::start_copy(void* arg) {
CurveSnapshotCopier* c = reinterpret_cast<CurveSnapshotCopier*>(arg); // 转换参数类型
c->copy(); // 调用复制方法
return NULL; // 返回NULL指针
}
// 执行复制操作
void CurveSnapshotCopier::copy() {
// 复制快照元数据和文件
// 1. 加载远程快照的元数据表
// 2. 根据配置决定是否过滤文件
// 3. 复制文件和附件
// 4. 关闭写入器和读取器
// 5. 处理错误情况
// 具体实现细节省略...
}
// 加载远程快照的元数据表
void CurveSnapshotCopier::load_meta_table() {
// 从远程快照加载元数据表到本地
// 具体实现细节省略...
}
// 加载远程快照的附件元数据表
void CurveSnapshotCopier::load_attach_meta_table() {
// 从远程快照加载附件元数据表到本地
// 具体实现细节省略...
}
// 在复制前过滤文件
int CurveSnapshotCopier::filter_before_copy(CurveSnapshotWriter* writer,
braft::SnapshotReader* last_snapshot) {
// 根据远程快照和本地快照决定哪些文件需要复制
// 具体实现细节省略...
}
// 复制单个文件
void CurveSnapshotCopier::copy_file(const std::string& filename, bool attch) {
// 复制指定的文件或附件
// 具体实现细节省略...
}
// 获取文件的相对路径
std::string CurveSnapshotCopier::get_rfilename(const std::string& filename) {
// 如果文件名包含'../',则返回相对路径,否则返回原始文件名
// 具体实现细节省略...
}
// 启动复制线程
void CurveSnapshotCopier::start() {
// 使用bthread_start_background启动复制线程
// 具体实现细节省略...
}
// 等待复制线程完成
void CurveSnapshotCopier::join() {
// 使用bthread_join等待线程结束
// 具体实现细节省略...
}
// 取消复制操作
void CurveSnapshotCopier::cancel() {
// 设置取消标志并尝试取消当前会话
// 具体实现细节省略...
}
// 初始化复制操作
int CurveSnapshotCopier::init(const std::string& uri) {
// 使用RemoteFileCopier的init方法初始化复制操作
// 具体实现细节省略...
}
} // namespace chunkserver
} // namespace curve
这段代码定义了一个CurveSnapshotCopier
类,它负责从远程源复制快照到本地存储。类中包含了构造函数、析构函数、复制操作的方法、加载元数据表的方法、过滤文件的方法、复制单个文件的方法、获取文件相对路径的方法、启动复制线程的方法、等待复制线程完成的方法、取消复制操作的方法以及初始化复制操作的方法。
copy
方法是复制操作的核心,它负责执行整个复制过程,包括加载元数据表、过滤文件、复制文件和附件、关闭写入器和读取器以及处理错误情况。
load_meta_table
和load_attach_meta_table
方法用于从远程快照加载元数据表和附件元数据表到本地。
filter_before_copy
方法用于在复制前根据远程快照和本地快照的状态决定哪些文件需要被复制。
copy_file
方法用于复制单个文件或附件。
get_rfilename
方法用于获取文件的相对路径,这在处理文件名时很重要,尤其是在处理包含../
的文件名时。
start
、join
和cancel
方法提供了对复制线程的控制,允许启动、等待和取消复制操作。
init
方法使用RemoteFileCopier
的init
方法来初始化复制操作,这是复制过程的第一步。
请注意,这段代码中的某些实现细节被省略了,例如具体的复制逻辑和错误处理。这些方法的具体实现将依赖于底层的文件系统和网络通信机制。
以下是对curve_filesystem_adaptor.cpp
文件中源码的详细分析,我将在代码中添加注释以解释每一部分的功能和作用。
/*
* Copyright (c) 2020 NetEase Inc.
* 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 "src/chunkserver/raftsnapshot/curve_filesystem_adaptor.h"
// 命名空间声明
namespace curve {
namespace chunkserver {
// 构造CurveFilesystemAdaptor对象
CurveFilesystemAdaptor::CurveFilesystemAdaptor(
std::shared_ptr<FilePool> chunkFilePool,
std::shared_ptr<LocalFileSystem> lfs)
: tempMetaPageContent(nullptr) { // 初始化临时元数据页内容为nullptr
// 初始化文件池和本地文件系统共享指针
lfs_ = lfs;
chunkFilePool_ = chunkFilePool;
// 获取文件池选项中的元数据页大小
uint64_t metapageSize = chunkFilePool->GetFilePoolOpt().metaPageSize;
// 分配新的内存用于临时元数据页
tempMetaPageContent = new (std::nothrow) char[metapageSize];
CHECK(tempMetaPageContent != nullptr); // 检查内存分配是否成功
memset(tempMetaPageContent, 0, metapageSize); // 将内存初始化为0
}
// 构造CurveFilesystemAdaptor对象(无文件池和本地文件系统)
CurveFilesystemAdaptor::CurveFilesystemAdaptor()
: tempMetaPageContent(nullptr) { // 初始化临时元数据页内容为nullptr
// 无参数构造函数
}
// 析构CurveFilesystemAdaptor对象
CurveFilesystemAdaptor::~CurveFilesystemAdaptor() {
// 释放临时元数据页内存
if (tempMetaPageContent != nullptr) {
delete[] tempMetaPageContent;
tempMetaPageContent = nullptr;
}
LOG(INFO) << "release raftsnapshot filesystem adaptor!"; // 记录日志
}
// 打开文件,返回文件适配器对象
braft::FileAdaptor* CurveFilesystemAdaptor::open(const std::string& path,
int oflag,
const ::google::protobuf::Message* file_meta,
butil::File::Error* e) {
// 省略具体实现,open方法通常涉及打开文件和返回文件适配器对象
}
// 删除文件或目录
bool CurveFilesystemAdaptor::delete_file(const std::string& path,
bool recursive) {
// 省略具体实现,delete_file方法用于删除文件或递归删除目录
}
// 递归删除目录及其内容
bool CurveFilesystemAdaptor::RecycleDirRecursive(const std::string& path) {
// 省略具体实现,RecycleDirRecursive方法用于递归删除目录及其内容
}
// 重命名文件或目录
bool CurveFilesystemAdaptor::rename(const std::string& old_path,
const std::string& new_path) {
// 省略具体实现,rename方法用于重命名文件或目录
}
// 设置过滤列表
void CurveFilesystemAdaptor::SetFilterList(const std::vector<std::string>& filter) {
// 省略具体实现,SetFilterList方法用于设置过滤列表
}
// 检查文件是否需要过滤
bool CurveFilesystemAdaptor::NeedFilter(const std::string& filename) {
// 省略具体实现,NeedFilter方法用于检查文件是否需要根据过滤列表进行过滤
}
} // namespace chunkserver
} // namespace curve
这段代码定义了一个CurveFilesystemAdaptor
类,它是一个文件系统适配器,用于与底层的文件系统交互。类中包含了构造函数、析构函数、打开文件的方法、删除文件或目录的方法、递归删除目录的方法、重命名文件或目录的方法、设置过滤列表的方法以及检查文件是否需要过滤的方法。
构造函数和析构函数负责初始化和清理资源。open
方法用于打开文件并返回一个文件适配器对象,它处理文件的打开、创建和元数据管理。delete_file
和RecycleDirRecursive
方法用于删除文件或目录,其中RecycleDirRecursive
是delete_file
的一个辅助方法,用于递归删除目录及其内容。rename
方法用于重命名文件或目录。SetFilterList
和NeedFilter
方法与文件过滤相关,允许适配器根据过滤列表决定是否处理特定的文件。
请注意,这段代码中的某些实现细节被省略了,例如具体的文件操作逻辑。这些方法的具体实现将依赖于底层的文件系统API和文件池管理机制。
以下是对curve_snapshot_attachment.cpp
文件中源码的详细分析,我将在代码中添加注释以解释每一部分的功能和作用。
/*
* Copyright (c) 2020 NetEase Inc.
* 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 "src/chunkserver/raftsnapshot/curve_snapshot_attachment.h"
#include "src/common/fs_util.h"
// 命名空间声明
namespace curve {
namespace chunkserver {
// 构造CurveSnapshotAttachment对象
CurveSnapshotAttachment::CurveSnapshotAttachment(
std::shared_ptr<LocalFileSystem> fs)
: fileHelper_(fs) { // 初始化文件辅助对象,用于与本地文件系统交互
}
// 列出附件文件
void CurveSnapshotAttachment::list_attach_files(
std::vector<std::string> *files,
const std::string& raftSnapshotPath) {
// 构建raft快照基础目录路径
std::string raftBaseDir = getCurveRaftBaseDir(raftSnapshotPath, RAFT_SNAP_DIR);
// 构建数据目录路径
std::string dataDir;
if (raftBaseDir[raftBaseDir.length() - 1] != '/') {
dataDir = raftBaseDir + "/" + RAFT_DATA_DIR;
} else {
dataDir = raftBaseDir + RAFT_DATA_DIR;
}
// 获取数据目录中的文件列表
std::vector<std::string> snapFiles;
int rc = fileHelper_.ListFiles(dataDir, nullptr, &snapFiles);
// 检查文件列表操作是否成功
CHECK(rc == 0) << "List dir failed.";
files->clear(); // 清空输出文件列表
// 遍历快照文件,构建相对路径,并添加到输出文件列表中
for (const auto& snapFile : snapFiles) {
std::string snapApath;
snapApath.append(dataDir);
snapApath.append("/").append(snapFile);
// 计算相对于raft快照路径的相对路径
std::string filePath = curve::common::CalcRelativePath(raftSnapshotPath, snapApath);
files->emplace_back(filePath);
}
}
} // namespace chunkserver
} // namespace curve
这段代码定义了一个CurveSnapshotAttachment
类,它用于处理与快照附件相关的操作。类中包含了构造函数和list_attach_files
方法。
构造函数接收一个指向LocalFileSystem
对象的共享指针,并将其存储在成员变量fileHelper_
中,用于后续与本地文件系统的交互。
list_attach_files
方法用于列出给定raft快照路径下的所有附件文件。它首先构建了快照的基础目录路径和数据目录路径,然后调用fileHelper_.ListFiles
方法来获取数据目录中的文件列表。如果文件列表操作成功,它将遍历文件列表,为每个文件构建一个相对于raft快照路径的路径,并将这些路径添加到输出文件列表中。
请注意,这段代码中的某些实现细节被省略了,例如getCurveRaftBaseDir
和curve::common::CalcRelativePath
函数的具体实现。这些函数用于处理路径相关的操作,如获取目录和文件的路径。list_attach_files
方法的具体实现将依赖于底层的文件系统API。
以下是对curve_snapshot.cpp
文件中源码的详细分析,我将在代码中添加注释以解释每一部分的功能和作用。
/*
* Copyright (c) 2020 NetEase Inc.
* 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 "src/chunkserver/raftsnapshot/curve_snapshot.h"
// 命名空间声明
namespace curve {
namespace chunkserver {
// CurveSnapshot类的构造函数
CurveSnapshot::CurveSnapshot() {
// 构造函数内容(如果有的话)
}
// CurveSnapshot类的析构函数
CurveSnapshot::~CurveSnapshot() {
// 析构函数内容(如果有的话)
}
// 获取快照的路径
std::string CurveSnapshot::get_path() {
// 返回快照的路径,这里为一个空字符串,实际实现可能会返回一个具体的路径
return std::string();
}
// 列出快照中的文件
void CurveSnapshot::list_files(std::vector<std::string> *files) {
// 这里应该是调用元数据表的方法来列出文件,但具体实现被省略了
// 实际实现可能会调用一个方法来填充files向量,列出所有文件
}
// 列出快照中的附件文件
void CurveSnapshot::list_attach_files(std::vector<std::string> *files) {
// 这里应该是调用元数据表的方法来列出附件文件,但具体实现被省略了
// 实际实现可能会调用一个方法来填充files向量,列出所有附件文件
}
// 获取特定文件的元数据
int CurveSnapshot::get_file_meta(const std::string& filename,
::google::protobuf::Message* file_meta) {
// 这里应该是调用元数据表的方法来获取文件的元数据,但具体实现被省略了
// 实际实现可能会调用一个方法,并传入文件名和指向文件元数据对象的指针
braft::LocalFileMeta* meta = NULL;
if (file_meta) {
meta = dynamic_cast<braft::LocalFileMeta*>(file_meta);
if (meta == NULL) {
return -1;
}
}
return _meta_table.get_file_meta(filename, meta);
}
} // namespace chunkserver
} // namespace curve
这段代码定义了一个CurveSnapshot
类,它是一个抽象类,用于表示一个快照对象。类中包含了构造函数、析构函数、获取快照路径的方法、列出快照中的文件和附件文件的方法、以及获取特定文件的元数据的方法。
get_path
方法应该返回快照的路径,但在这个抽象类中,它返回一个空字符串。这个方法的实现应该在派生类中具体化,以返回正确的路径。
list_files
和list_attach_files
方法用于列出快照中的所有文件和附件文件。这些方法的实现被省略了,但它们应该调用元数据表的相关方法来获取文件列表,并将其填充到传入的files
向量中。
get_file_meta
方法用于获取指定文件的元数据。它首先检查传入的file_meta
指针是否有效,并将文件元数据填充到braft::LocalFileMeta
对象中。如果file_meta
是一个有效的指针,方法会尝试从元数据表中获取文件的元数据,并返回操作的结果。
请注意,这段代码中的某些实现细节被省略了,例如具体的文件操作逻辑。这些方法的具体实现将依赖于底层的文件系统API和元数据管理机制。CurveSnapshot
类提供了一个框架,用于在分布式系统中管理和访问快照数据。
以下是对curve_snapshot_reader.cpp
文件中源码的详细分析,我将在代码中添加注释以解释每一部分的功能和作用。
/*
* Copyright (c) 2020 NetEase Inc.
* 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 "src/chunkserver/raftsnapshot/curve_snapshot_reader.h"
#include "src/chunkserver/raftsnapshot/curve_file_service.h"
// 命名空间声明
namespace curve {
namespace chunkserver {
// 构造CurveSnapshotReader对象
CurveSnapshotReader::CurveSnapshotReader(const std::string& path,
braft::FileSystemAdaptor* fs,
braft::SnapshotThrottle* throttle)
: _path(path), // 初始化快照路径
_fs(fs), // 初始化文件系统适配器
_snapshot_throttle(throttle), // 初始化快照节流对象
_meta_table(), // 初始化元数据表
_reader_id(0), // 初始化读取器ID
_addr() // 初始化地址
{
// 构造函数内容
}
// 析构CurveSnapshotReader对象
CurveSnapshotReader::~CurveSnapshotReader() {
destroy_reader_in_file_service(); // 销毁文件服务中的读取器
}
// 初始化快照读取器
int CurveSnapshotReader::init() {
if (!_fs->directory_exists(_path)) { // 检查快照目录是否存在
set_error(ENOENT, "Not such _path : %s", _path.c_str());
return ENOENT; // 如果不存在,设置错误并返回
}
std::string meta_path = _path + "/" BRAFT_SNAPSHOT_META_FILE; // 构造元数据文件路径
if (_meta_table.load_from_file(_fs, meta_path) != 0) { // 加载元数据表
set_error(EIO, "Fail to load meta");
return EIO; // 如果加载失败,设置错误并返回
}
return 0; // 初始化成功
}
// 加载快照元数据到braft::SnapshotMeta对象
int CurveSnapshotReader::load_meta(braft::SnapshotMeta* meta) {
if (!_meta_table.has_meta()) { // 检查是否有元数据
return -1; // 如果没有,返回错误
}
*meta = _meta_table.meta(); // 将元数据复制到输出参数
return 0; // 成功
}
// 获取快照的索引
int64_t CurveSnapshotReader::snapshot_index() {
butil::FilePath path(_path); // 创建路径对象
int64_t index = 0; // 初始化索引
int ret = sscanf(path.BaseName().value().c_str(), // 从路径基础名称中解析索引
BRAFT_SNAPSHOT_PATTERN, &index);
CHECK_EQ(ret, 1) << "Invalid snapshot index"; // 检查解析结果
return index; // 返回索引
}
// 列出快照中的文件
void CurveSnapshotReader::list_files(std::vector<std::string> *files) {
return _meta_table.list_files(files); // 调用元数据表的list_files方法
}
// 获取特定文件的元数据
int CurveSnapshotReader::get_file_meta(const std::string& filename,
::google::protobuf::Message* file_meta) {
braft::LocalFileMeta* meta = NULL; // 创建局部文件元数据指针
if (file_meta) {
meta = dynamic_cast<braft::LocalFileMeta*>(file_meta); // 尝试类型转换
if (meta == NULL) {
return -1; // 如果转换失败,返回错误
}
}
return _meta_table.get_file_meta(filename, meta); // 从元数据表获取文件元数据
}
// 生成用于复制的URI
std::string CurveSnapshotReader::generate_uri_for_copy() {
// 如果地址未指定,记录错误并返回空字符串
if (_addr == butil::EndPoint()) {
LOG(ERROR) << "Address is not specified, path: " << _path;
return std::string();
}
// 如果读取器ID未指定,尝试打开快照文件并注册读取器
if (_reader_id == 0) {
scoped_refptr<CurveSnapshotFileReader> reader(new CurveSnapshotFileReader(_fs, _path, _snapshot_throttle));
reader->set_meta_table(_meta_table);
if (!reader->open()) {
LOG(ERROR) << "Open snapshot=" << _path << " failed";
return std::string();
}
if (kCurveFileService.add_reader(reader.get(), &_reader_id) != 0) {
LOG(ERROR) << "Fail to add reader to file_service, path: " << _path;
return std::string();
}
}
// 构建并返回用于复制的URI
std::ostringstream oss;
oss << "remote://" << _addr << "/" << _reader_id;
return oss.str();
}
// 销毁文件服务中的读取器
void CurveSnapshotReader::destroy_reader_in_file_service() {
if (_reader_id != 0) {
CHECK_EQ(0, kCurveFileService.remove_reader(_reader_id)); // 移除读取器
_reader_id = 0; // 重置读取器ID
}
}
} // namespace chunkserver
} // namespace curve
这段代码定义了一个CurveSnapshotReader
类,它用于读取和管理快照数据。类中包含了构造函数、析构函数、初始化方法、加载快照元数据的方法、获取快照索引的方法、列出快照中的文件的方法、获取特定文件的元数据的方法、生成用于复制的URI的方法以及销毁文件服务中的读取器的方法。
构造函数初始化了快照读取器的成员变量,包括快照路径、文件系统适配器、快照节流对象以及元数据表。
析构函数负责清理资源,特别是调用destroy_reader_in_file_service
方法来确保从文件服务中移除读取器。
init
方法检查快照目录是否存在,并尝试加载元数据表。如果目录不存在或元数据表加载失败,它会设置错误并返回相应的错误码。
load_meta
方法检查是否有元数据,并将其复制到传入的braft::SnapshotMeta
对象中。
snapshot_index
方法从快照路径中解析出快照的索引。
list_files
方法调用元数据表的list_files
方法来列出快照中的所有文件。
get_file_meta
方法从元数据表中获取特定文件的元数据,并将其填充到传入的文件元数据对象中。
generate_uri_for_copy
方法生成一个用于复制的URI,这个URI包含了快照的地址和读取器ID。
destroy_reader_in_file_service
方法从文件服务中移除读取器,并重置读取器ID。
请注意,这段代码中的某些实现细节被省略了,例如具体的文件操作逻辑和错误处理。这些方法的具体实现将依赖于底层的文件系统API和元数据管理机制。CurveSnapshotReader
类提供了一个框架,用于在分布式系统中读取和管理快照数据。
以下是对curve_snapshot_storage.cpp
文件中源码的详细分析,我将在代码中添加注释以解释每一部分的功能和作用。
/*
* Copyright (c) 2020 NetEase Inc.
* 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 "src/chunkserver/raftsnapshot/curve_snapshot_storage.h"
// 命名空间声明
namespace braft {
DECLARE_bool(raft_create_parent_directories); // 声明braft模块中的一个布尔配置项
}
namespace curve {
namespace chunkserver {
// 注册CurveSnapshotStorage类到braft模块
void RegisterCurveSnapshotStorageOrDie() {
static CurveSnapshotStorage snapshotStorage; // 创建一个静态实例
braft::snapshot_storage_extension()->
RegisterOrDie("curve", &snapshotStorage); // 注册存储实例
}
// CurveSnapshotStorage类的成员变量声明
const char* CurveSnapshotStorage::_s_temp_path = "temp"; // 临时路径名称
butil::EndPoint CurveSnapshotStorage::_addr; // 存储的地址
braft::FileSystemAdaptor* CurveSnapshotStorage::_fs = NULL; // 文件系统适配器
// 构造CurveSnapshotStorage对象
CurveSnapshotStorage::CurveSnapshotStorage(const std::string& path)
: _path(path), // 初始化路径
_last_snapshot_index(0), // 初始化最后快照索引为0
_ref_map(), // 初始化引用计数映射
_mutex() { // 初始化互斥锁
// 构造函数内容
}
// 初始化CurveSnapshotStorage
int CurveSnapshotStorage::init() {
// 省略具体实现,初始化方法通常涉及创建目录和清理旧快照等操作
}
// 引用快照
void CurveSnapshotStorage::ref(const int64_t index) {
// 省略具体实现,引用方法用于增加快照的引用计数
}
// 取消引用快照
void CurveSnapshotStorage::unref(const int64_t index) {
// 省略具体实现,取消引用方法用于减少快照的引用计数,并在引用计数为0时删除快照
}
// 创建快照写入器
braft::SnapshotWriter* CurveSnapshotStorage::create() {
// 省略具体实现,创建方法用于创建一个新的快照写入器
}
// 创建快照复制器
braft::SnapshotCopier* CurveSnapshotStorage::start_to_copy_from(
const std::string& uri) {
// 省略具体实现,开始复制方法用于从指定URI复制快照
}
// 关闭快照复制器
int CurveSnapshotStorage::close(braft::SnapshotCopier* copier) {
// 省略具体实现,关闭方法用于关闭快照复制器并释放资源
}
// 从复制器复制快照
braft::SnapshotReader* CurveSnapshotStorage::copy_from(const std::string& uri) {
// 省略具体实现,复制方法用于从复制器复制快照并返回读取器
}
// 关闭快照读取器
int CurveSnapshotStorage::close(braft::SnapshotReader* reader) {
// 省略具体实现,关闭方法用于关闭快照读取器并释放资源
}
// 设置远程文件过滤
int CurveSnapshotStorage::set_filter_before_copy_remote() {
// 省略具体实现,设置过滤方法用于在复制前设置文件过滤
}
// 设置文件系统适配器
int CurveSnapshotStorage::set_file_system_adaptor(
braft::FileSystemAdaptor* fs) {
_fs = fs; // 设置文件系统适配器
return 0; // 成功
}
// 设置快照节流
int CurveSnapshotStorage::set_snapshot_throttle(
braft::SnapshotThrottle* snapshot_throttle) {
_snapshot_throttle = snapshot_throttle; // 设置快照节流对象
return 0; // 成功
}
// 创建CurveSnapshotStorage实例
braft::SnapshotStorage* CurveSnapshotStorage::new_instance(
const std::string& uri) const {
return new CurveSnapshotStorage(uri); // 创建并返回一个新的CurveSnapshotStorage实例
}
} // namespace chunkserver
} // namespace curve
这段代码定义了一个CurveSnapshotStorage
类,它用于在分布式系统中管理和存储快照数据。类中包含了构造函数、初始化方法、引用和取消引用快照的方法、创建快照写入器和复制器的方法、关闭复制器和读取器的方法、设置远程文件过滤的方法、设置文件系统适配器和快照节流的方法,以及创建CurveSnapshotStorage
实例的方法。
构造函数初始化了快照存储的成员变量,包括存储路径、最后快照索引、引用计数映射以及互斥锁。
init
方法负责初始化快照存储,这通常涉及创建必要的目录和清理旧快照。
ref
和unref
方法用于管理快照的引用计数,当引用计数增加或减少时,这些方法会相应地更新计数。
create
方法用于创建一个新的快照写入器,以便可以写入新的快照数据。
start_to_copy_from
方法启动一个新的快照复制器,用于从指定的URI复制快照数据。
close
方法用于关闭快照复制器和读取器,并释放相关资源。
set_filter_before_copy_remote
方法用于在复制快照数据之前设置文件过滤规则,这有助于排除不需要复制的文件。
set_file_system_adaptor
和set_snapshot_throttle
方法分别用于设置文件系统适配器和快照节流对象,这些对象用于控制文件操作和快照数据的传输速率。
new_instance
方法用于创建一个新的CurveSnapshotStorage
实例,这个方法通常在快照存储需要被复制或迁移时调用。
请注意,这段代码中的某些实现细节被省略了,例如具体的文件操作逻辑和错误处理。这些方法的具体实现将依赖于底层的文件系统API和快照管理机制。CurveSnapshotStorage
类提供了一个框架,用于在分布式系统中管理和存储快照数据。