源码路径
curve-release2.2\src\chunkserver\datastore
1.chunkserver_datastore.cpp
2.chunkserver_snapshot.cpp
3.chunkserver_chunkfile.cpp
4.datastore_file_helper.cpp
5.file_pool.cpp
在chunkserver_datastore.cpp
文件中,定义了CSDataStore
类及其相关方法。以下是该文件中函数的方法分析,采用代码注释的方式进行说明:
// CSDataStore类的构造函数,初始化数据存储的基本属性
CSDataStore::CSDataStore(std::shared_ptr<LocalFileSystem> lfs,
std::shared_ptr<FilePool> chunkFilePool,
const DataStoreOptions& options)
: ... {
// 检查必需的参数是否有效
CHECK(!baseDir_.empty()) << "Create datastore failed";
CHECK(lfs_ != nullptr) << "Create datastore failed";
CHECK(chunkFilePool_ != nullptr) << "Create datastore failed";
}
// CSDataStore类的析构函数
CSDataStore::~CSDataStore() {
// 清理资源,如果有必要的话
}
// 初始化数据存储,确保基础目录存在,并加载已有的块文件
bool CSDataStore::Initialize() {
// 检查基础目录是否存在,不存在则创建
if (!lfs_->DirExists(baseDir_.c_str())) {
int rc = lfs_->Mkdir(baseDir_.c_str());
if (rc < 0) {
LOG(ERROR) << "Create " << baseDir_ << " failed.";
return false;
}
}
// 列出基础目录下的所有文件
vector<string> files;
int rc = lfs_->List(baseDir_, &files);
if (rc < 0) {
LOG(ERROR) << "List " << baseDir_ << " failed.";
return false;
}
// 遍历文件列表,加载块文件和快照
for (size_t i = 0; i < files.size(); ++i) {
FileNameOperator::FileInfo info = FileNameOperator::ParseFileName(files[i]);
if (info.type == FileNameOperator::FileType::CHUNK) {
// 加载块文件
CSErrorCode errorCode = loadChunkFile(info.id);
if (errorCode != CSErrorCode::Success) {
LOG(ERROR) << "Load chunk file failed: " << files[i];
return false;
}
} else if (info.type == FileNameOperator::FileType::SNAPSHOT) {
// 加载快照文件
string chunkFilePath = baseDir_ + "/" + FileNameOperator::GenerateChunkFileName(info.id);
// 如果块文件不存在,记录警告并继续
if (!lfs_->FileExists(chunkFilePath)) {
LOG(WARNING) << "Can't find snapshot " << files[i] << "' chunk.";
continue;
}
// 加载块文件
CSErrorCode errorCode = loadChunkFile(info.id);
if (errorCode != CSErrorCode::Success) {
LOG(ERROR) << "Load chunk file failed.";
return false;
}
// 加载快照到内存
errorCode = metaCache_.Get(info.id)->LoadSnapshot(info.sn);
if (errorCode != CSErrorCode::Success) {
LOG(ERROR) << "Load snapshot failed.";
return false;
}
} else {
// 未知文件类型,记录警告
LOG(WARNING) << "Unknown file: " << files[i];
}
}
LOG(INFO) << "Initialize data store success.";
return true;
}
// 删除指定序列号的块
CSErrorCode CSDataStore::DeleteChunk(ChunkID id, SequenceNum sn) {
auto chunkFile = metaCache_.Get(id);
if (chunkFile != nullptr) {
CSErrorCode errorCode = chunkFile->Delete(sn);
if (errorCode != CSErrorCode::Success) {
LOG(WARNING) << "Delete chunk file failed. ChunkID = " << id;
return errorCode;
}
metaCache_.Remove(id);
}
return CSErrorCode::Success;
}
// 读取块数据
CSErrorCode CSDataStore::ReadChunk(ChunkID id,
SequenceNum sn,
char *buf,
off_t offset,
size_t length) {
auto chunkFile = metaCache_.Get(id);
if (chunkFile == nullptr) {
return CSErrorCode::ChunkNotExistError;
}
CSErrorCode errorCode = chunkFile->Read(buf, offset, length);
if (errorCode != CSErrorCode::Success) {
LOG(WARNING) << "Read chunk file failed. ChunkID = " << id;
return errorCode;
}
return CSErrorCode::Success;
}
// 创建新的块文件
CSErrorCode CSDataStore::CreateChunkFile(const ChunkOptions &options, CSChunkFilePtr* chunkFile) {
// 检查位置信息是否过长
if (!options.location.empty() && options.location.size() > locationLimit_) {
LOG(ERROR) << "Location is too long. ChunkID = " << options.id;
return CSErrorCode::InvalidArgError;
}
// 创建新的块文件对象
auto tempChunkFile = std::make_shared<CSChunkFile>(lfs_, chunkFilePool_, options);
CSErrorCode errorCode = tempChunkFile->Open(true);
if (errorCode != CSErrorCode::Success) {
LOG(WARNING) << "Create chunk file failed. ChunkID = " << options.id;
return errorCode;
}
// 如果有并发操作创建相同的块文件,确保使用相同的块文件对象
*chunkFile = metaCache_.Set(options.id, tempChunkFile);
return CSErrorCode::Success;
}
// 写入数据到块文件
CSErrorCode CSDataStore::WriteChunk(ChunkID id,
SequenceNum sn,
const butil::IOBuf& buf,
off_t offset,
size_t length,
uint32_t* cost,
const std::string& cloneSourceLocation) {
// 检查序列号是否有效
if (sn == kInvalidSeq) {
LOG(ERROR) << "Sequence num should not be zero. ChunkID = " << id;
return CSErrorCode::InvalidArgError;
}
auto chunkFile = metaCache_.Get(id);
// 如果块文件不存在,首先创建块文件
if (chunkFile == nullptr) {
ChunkOptions options;
// 设置块文件的选项
... // 初始化options
CSErrorCode errorCode = CreateChunkFile(options, &chunkFile);
if (errorCode != CSErrorCode::Success) {
return errorCode;
}
}
// 写入数据到块文件
CSErrorCode errorCode = chunkFile->Write(sn, buf, offset, length, cost);
if (errorCode != CSErrorCode::Success) {
LOG(WARNING) << "Write chunk file failed. ChunkID = " << id;
return errorCode;
}
return CSErrorCode::Success;
}
// 同步块文件,确保数据写入磁盘
CSErrorCode CSDataStore::SyncChunk(ChunkID id) {
auto chunkFile = metaCache_.Get(id);
if (chunkFile == nullptr) {
LOG(WARNING) << "Sync chunk not exist, ChunkID = " << id;
return CSErrorCode::Success;
}
CSErrorCode errorCode = chunkFile->Sync();
if (errorCode != CSErrorCode::Success) {
LOG(WARNING) << "Sync chunk file failed. ChunkID = " << id;
return errorCode;
}
return CSErrorCode::Success;
}
// 其他方法...
以上是对chunkserver_datastore.cpp
中部分方法的分析,每个方法都有其特定的功能和错误处理机制。通过这些方法,CSDataStore
类能够管理数据块的存储、检索和更新。
在chunkserver_snapshot.cpp
文件中,定义了CSSnapshot
类及其相关方法。以下是该文件中函数的方法分析,采用代码注释的方式进行说明:
// CSSnapshot类的构造函数,初始化快照的基本属性
CSSnapshot::CSSnapshot(std::shared_ptr<LocalFileSystem> lfs,
std::shared_ptr<FilePool> chunkFilePool,
const ChunkOptions& options)
: fd_(-1), // 文件描述符初始化为-1,表示文件未打开
chunkId_(options.id), // 设置块ID
size_(options.chunkSize), // 设置块大小
pageSize_(options.pageSize), // 设置页大小
baseDir_(options.baseDir), // 设置基础目录
lfs_(lfs), // 设置本地文件系统对象
chunkFilePool_(chunkFilePool), // 设置文件池对象
metric_(options.metric), // 设置度量对象
metaPage_(options) // 设置快照元数据页
{
// 检查基础目录是否为空
CHECK(!baseDir_.empty()) << "Create snapshot failed";
CHECK(lfs_ != nullptr) << "Create snapshot failed";
// 初始化位图,表示哪些页是脏的(已修改的)
uint32_t bits = size_ / pageSize_;
metaPage_.bitmap = std::make_shared<Bitmap>(bits);
// 如果度量对象不为空,增加快照计数
if (metric_ != nullptr) {
metric_->snapshotCount++; // 增加快照计数
}
}
// CSSnapshot类的析构函数,清理资源
CSSnapshot::~CSSnapshot() {
// 关闭文件描述符,如果已打开
if (fd_ >= 0) {
lfs_->Close(fd_);
}
// 如果度量对象不为空,减少快照计数
if (metric_ != nullptr) {
metric_->snapshotCount--; // 减少快照计数
}
}
// 打开快照文件,创建或打开快照文件,并加载元数据页
CSErrorCode CSSnapshot::Open(bool createFile) {
string snapshotPath = path(); // 获取快照文件路径
// 如果需要创建文件,并且快照文件不存在,则创建新文件
if (createFile && !lfs_->FileExists(snapshotPath)) {
// 创建新文件并初始化元数据页
// ... 创建文件和初始化元数据页的代码 ...
}
// 打开快照文件
int rc = lfs_->Open(snapshotPath, O_RDWR|O_NOATIME|O_DSYNC);
if (rc < 0) {
LOG(ERROR) << "Error occurred when opening file. filepath = " << snapshotPath;
return CSErrorCode::InternalError;
}
fd_ = rc; // 保存文件描述符
// 获取文件信息,检查文件大小是否正确
struct stat fileInfo;
rc = lfs_->Fstat(fd_, &fileInfo);
if (rc < 0) {
LOG(ERROR) << "Error occurred when stating file. filepath = " << snapshotPath;
return CSErrorCode::InternalError;
}
if (fileInfo.st_size != fileSize()) {
LOG(ERROR) << "Wrong file size. filepath = " << snapshotPath;
return CSErrorCode::FileFormatError;
}
// 加载元数据页
return loadMetaPage();
}
// 从快照文件中读取数据
CSErrorCode CSSnapshot::Read(char *buf, off_t offset, size_t length) {
// 从指定偏移量和长度的快照文件中读取数据到缓冲区
int rc = readData(buf, offset, length); // 调用实际的读取数据方法
if (rc < 0) {
LOG(ERROR) << "Error occurred when reading snapshot. filepath = " << path();
return CSErrorCode::InternalError;
}
return CSErrorCode::Success;
}
// 向快照文件写入数据
CSErrorCode CSSnapshot::Write(const char *buf, off_t offset, size_t length) {
int rc = writeData(buf, offset, length); // 调用实际的写入数据方法
if (rc < 0) {
LOG(ERROR) << "Write snapshot failed. ChunkID: " << chunkId_
<< ",snapshot sn: " << metaPage_.sn;
return CSErrorCode::InternalError;
}
// 更新脏页位图
uint32_t pageBeginIndex = offset / pageSize_;
uint32_t pageEndIndex = (offset + length - 1) / pageSize_;
for (uint32_t i = pageBeginIndex; i <= pageEndIndex; ++i) {
dirtyPages_.insert(i); // 将页索引添加到脏页集合中
}
return CSErrorCode::Success;
}
// 将快照文件中修改的数据刷新到磁盘
CSErrorCode CSSnapshot::Flush() {
// 创建临时元数据页副本,用于更新
SnapshotMetaPage tempMeta = metaPage_;
// 更新所有脏页的状态
for (auto pageIndex : dirtyPages_) {
tempMeta.bitmap->Set(pageIndex);
}
// 更新元数据页
CSErrorCode errorCode = updateMetaPage(&tempMeta);
if (errorCode == CSErrorCode::Success) {
metaPage_.bitmap = tempMeta.bitmap; // 更新元数据页的位图
}
dirtyPages_.clear(); // 清空脏页集合
return errorCode;
}
// 加载快照文件的元数据页
CSErrorCode CSSnapshot::loadMetaPage() {
// 读取元数据页到缓冲区
std::unique_ptr<char[]> buf(new char[pageSize_]);
memset(buf.get(), 0, pageSize_);
int rc = readMetaPage(buf.get());
if (rc < 0) {
LOG(ERROR) << "Error occurred when reading metaPage_. filepath = " << path();
return CSErrorCode::InternalError;
}
// 从缓冲区解码元数据页信息
return metaPage_.decode(buf.get());
}
// 其他方法...
以上是对chunkserver_snapshot.cpp
中部分方法的分析,每个方法都有其特定的功能和错误处理机制。CSSnapshot
类管理了快照的创建、读取、写入和刷新等操作,确保数据的一致性和完整性。
在chunkserver_chunkfile.cpp
文件中,定义了CSChunkFile
类及其相关方法。以下是该文件中函数的方法分析,采用代码注释的方式进行说明:
// CSChunkFile类的构造函数,初始化数据块文件的基本属性
CSChunkFile::CSChunkFile(std::shared_ptr<LocalFileSystem> lfs,
std::shared_ptr<FilePool> chunkFilePool,
const ChunkOptions& options)
: fd_(-1), // 文件描述符初始化为-1,表示文件未打开
size_(options.chunkSize), // 设置数据块大小
pageSize_(options.pageSize), // 设置页大小
chunkId_(options.id), // 设置数据块ID
baseDir_(options.baseDir), // 设置基础目录
isCloneChunk_(false), // 标记是否为克隆数据块
snapshot_(nullptr), // 初始化快照对象为nullptr
chunkFilePool_(chunkFilePool), // 设置文件池对象
lfs_(lfs), // 设置本地文件系统对象
metric_(options.metric), // 设置度量对象
enableOdsyncWhenOpenChunkFile_(options.enableOdsyncWhenOpenChunkFile) // 是否在打开文件时使用O_DSYNC标志
{
// 初始化元数据页
metaPage_.sn = options.sn; // 设置当前序列号
metaPage_.correctedSn = options.correctedSn; // 设置已修正的序列号
metaPage_.location = options.location; // 设置位置信息
// 如果位置信息不为空,则为克隆数据块,并初始化位图
if (!metaPage_.location.empty()) {
uint32_t bits = size_ / pageSize_;
metaPage_.bitmap = std::make_shared<Bitmap>(bits); // 初始化位图
}
// 如果度量对象不为空,增加数据块文件计数
if (metric_ != nullptr) {
metric_->chunkFileCount++; // 增加数据块文件计数
}
}
// CSChunkFile类的析构函数,清理资源
CSChunkFile::~CSChunkFile() {
// 如果快照对象不为空,释放资源
if (snapshot_ != nullptr) {
delete snapshot_;
snapshot_ = nullptr;
}
// 关闭文件描述符,如果已打开
if (fd_ >= 0) {
lfs_->Close(fd_);
}
// 如果度量对象不为空,减少数据块文件计数
if (metric_ != nullptr) {
metric_->chunkFileCount--; // 减少数据块文件计数
if (isCloneChunk_) {
metric_->cloneChunkCount--; // 减少克隆数据块计数
}
}
}
// 打开数据块文件,创建或打开数据块文件,并加载元数据页
CSErrorCode CSChunkFile::Open(bool createFile) {
string chunkFilePath = path(); // 获取数据块文件路径
// 如果需要创建文件,并且数据块文件不存在,则创建新文件
if (createFile && !lfs_->FileExists(chunkFilePath)) {
// 创建新文件并初始化元数据页
// ... 创建文件和初始化元数据页的代码 ...
}
// 打开数据块文件
int rc = -1;
if (enableOdsyncWhenOpenChunkFile_) {
rc = lfs_->Open(chunkFilePath, O_RDWR|O_NOATIME|O_DSYNC); // 使用O_DSYNC标志打开文件
} else {
rc = lfs_->Open(chunkFilePath, O_RDWR|O_NOATIME); // 不使用O_DSYNC标志打开文件
}
if (rc < 0) {
LOG(ERROR) << "Error occurred when opening file. filepath = " << chunkFilePath;
return CSErrorCode::InternalError;
}
fd_ = rc; // 保存文件描述符
struct stat fileInfo;
rc = lfs_->Fstat(fd_, &fileInfo);
if (rc < 0) {
LOG(ERROR) << "Error occurred when stating file. filepath = " << chunkFilePath;
return CSErrorCode::InternalError;
}
if (fileInfo.st_size != fileSize()) {
LOG(ERROR) << "Wrong file size. filepath = " << chunkFilePath;
return CSErrorCode::FileFormatError;
}
// 加载元数据页
CSErrorCode errCode = loadMetaPage();
// 检查是否为克隆数据块
if (!metaPage_.location.empty() && !isCloneChunk_) {
if (metric_ != nullptr) {
metric_->cloneChunkCount++; // 增加克隆数据块计数
}
isCloneChunk_ = true; // 设置为克隆数据块
}
return errCode;
}
// 从数据块文件中读取数据
CSErrorCode CSChunkFile::Read(char *buf, off_t offset, size_t length) {
ReadLockGuard readGuard(rwLock_); // 读取时加读锁
if (!CheckOffsetAndLength(offset, length, pageSize_)) {
LOG(ERROR) << "Read chunk failed, invalid offset or length.";
return CSErrorCode::InvalidArgError;
}
int rc = readData(buf, offset, length); // 调用实际的读取数据方法
if (rc < 0) {
LOG(ERROR) << "Read chunk file failed. chunkId = " << chunkId_
<< ", chunk sn: " << metaPage_.sn;
return CSErrorCode::InternalError;
}
return CSErrorCode::Success;
}
// 向数据块文件写入数据
CSErrorCode CSChunkFile::Write(SequenceNum sn,
const butil::IOBuf& buf,
off_t offset,
size_t length,
uint32_t* cost) {
WriteLockGuard writeGuard(rwLock_); // 写入时加写锁
if (!CheckOffsetAndLength(offset, length, pageSize_)) {
LOG(ERROR) << "Write chunk failed, invalid offset or length.";
return CSErrorCode::InvalidArgError;
}
// 检查序列号是否有效
if (sn < metaPage_.sn || sn < metaPage_.correctedSn) {
LOG(WARNING) << "Backward write request.";
return CSErrorCode::BackwardRequestError;
}
// 如果需要创建快照,则创建快照
if (needCreateSnapshot(sn)) {
// ... 创建快照的代码 ...
}
// 如果序列号大于当前数据块的序列号,则更新元数据页
if (sn > metaPage_.sn) {
// ... 更新元数据页的代码 ...
}
// 如果是克隆数据块,先将数据复制到快照文件中
if (needCow(sn)) {
// ... 复制数据到快照文件的代码 ...
}
// 写入数据到数据块文件
int rc = writeData(buf, offset, length);
if (rc < 0) {
LOG(ERROR) << "Write data to chunk file failed. chunkId = " << chunkId_
<< ", request sn: " << sn
<< ", chunk sn: " << metaPage_.sn;
return CSErrorCode::InternalError;
}
// 如果是克隆数据块,更新位图
CSErrorCode errorCode = flush();
if (errorCode != CSErrorCode::Success) {
LOG(ERROR) << "Write data to chunk file failed. chunkId = " << chunkId_
<< ", request sn: " << sn
<< ", chunk sn: " << metaPage_.sn;
return errorCode;
}
return CSErrorCode::Success;
}
// 同步数据块文件,确保所有数据都已写入磁盘
CSErrorCode CSChunkFile::Sync() {
WriteLockGuard writeGuard(rwLock_); // 同步时加写锁
int rc = SyncData(); // 调用实际的同步数据方法
if (rc < 0) {
LOG(ERROR) << "Sync data failed, chunkId: " << chunkId_;
return CSErrorCode::InternalError;
}
return CSErrorCode::Success;
}
// 其他方法...
以上是对chunkserver_chunkfile.cpp
中部分方法的分析,每个方法都有其特定的功能和错误处理机制。CSChunkFile
类管理了数据块文件的创建、读取、写入、同步等操作,确保数据的一致性和完整性。通过这些方法,CSChunkFile
类能够处理数据块的存储、检索和更新。
在datastore_file_helper.cpp
文件中,定义了DatastoreFileHelper
类及其相关方法。以下是该文件中函数的方法分析,采用代码注释的方式进行说明:
// DatastoreFileHelper类的ListFiles方法,列出给定目录下的块文件和快照文件
int DatastoreFileHelper::ListFiles(const string& baseDir,
vector<string>* chunkFiles,
vector<string>* snapFiles) {
vector<string> files; // 用于存储目录下的所有文件
int rc = fs_->List(baseDir, &files); // 调用文件系统接口列出目录内容
if (rc < 0 && rc != -ENOENT) { // 如果返回错误,且错误不是目录不存在
LOG(ERROR) << "List " << baseDir << " failed.";
return -1; // 返回错误代码
}
for (auto& file : files) { // 遍历所有文件
FileNameOperator::FileInfo info = FileNameOperator::ParseFileName(file); // 解析文件名
if (info.type == FileNameOperator::FileType::CHUNK) { // 如果是块文件
if (chunkFiles != nullptr) { // 如果提供了接收块文件的容器
chunkFiles->emplace_back(file); // 添加到块文件列表
}
} else if (info.type == FileNameOperator::FileType::SNAPSHOT) { // 如果是快照文件
if (snapFiles != nullptr) { // 如果提供了接收快照文件的容器
snapFiles->emplace_back(file); // 添加到快照文件列表
}
} else { // 未知文件类型
LOG(WARNING) << "Unknown file: " << file;
}
}
return 0; // 成功返回0
}
// DatastoreFileHelper类的IsSnapshotFile方法,判断给定文件名是否为快照文件
bool DatastoreFileHelper::IsSnapshotFile(const string& fileName) {
FileNameOperator::FileInfo info = FileNameOperator::ParseFileName(fileName); // 解析文件名
return info.type == FileNameOperator::FileType::SNAPSHOT; // 如果类型为快照,则返回true
}
// DatastoreFileHelper类的IsChunkFile方法,判断给定文件名是否为块文件
bool DatastoreFileHelper::IsChunkFile(const string& fileName) {
FileNameOperator::FileInfo info = FileNameOperator::ParseFileName(fileName); // 解析文件名
return info.type == FileNameOperator::FileType::CHUNK; // 如果类型为块,则返回true
}
DatastoreFileHelper
类提供了一系列辅助方法,用于处理文件系统中的块文件和快照文件。ListFiles
方法用于列出特定目录下的所有块文件和快照文件,将它们分别存储在提供的容器中。IsSnapshotFile
和IsChunkFile
方法用于判断给定的文件名是否分别对应快照文件和块文件。这些方法通过解析文件名来确定文件类型,对于未知的文件类型,会记录警告日志。这些辅助方法简化了文件类型判断和文件列表操作的复杂性,使得其他代码能够更容易地处理文件系统相关的任务。
在file_pool.cpp
文件中,定义了FilePool
类及其相关方法。以下是该文件中函数的方法分析,采用代码注释的方式进行说明:
// FilePool类的构造函数,初始化文件池
FilePool::FilePool(std::shared_ptr<LocalFileSystem> fsptr)
: currentmaxfilenum_(0), // 当前文件编号初始化为0
cleanAlived_(false), // 清洁线程活跃标记初始化为false
fsptr_(fsptr), // 保存传入的文件系统指针
writeBuffer_(new char[poolOpt_.bytesPerWrite]) { // 分配写缓冲区
memset(writeBuffer_.get(), 0, poolOpt_.bytesPerWrite); // 将写缓冲区初始化为0
}
// FilePool类的初始化方法,准备文件池以供使用
bool FilePool::Initialize(const FilePoolOptions& cfopt) {
poolOpt_ = cfopt; // 保存文件池选项
// 如果文件池选项指定从文件池获取文件
if (poolOpt_.getFileFromPool) {
if (!CheckValid()) { // 检查文件池是否有效
LOG(ERROR) << "check valid failed!";
return false;
}
// 扫描文件池内部,初始化文件列表
return ScanInternal();
} else { // 否则,创建新的文件池目录
currentdir_ = poolOpt_.filePoolDir; // 设置当前目录为文件池目录
if (!fsptr_->DirExists(currentdir_.c_str())) { // 如果目录不存在,尝试创建
return fsptr_->Mkdir(currentdir_.c_str()) == 0;
}
}
return true; // 初始化成功
}
// FilePool类的清洁方法,用于清理指定的块
bool FilePool::CleanChunk(uint64_t chunkid, bool onlyMarked) {
std::string chunkpath = currentdir_ + "/" + std::to_string(chunkid); // 构建块文件路径
int fd = fsptr_->Open(chunkpath, O_RDWR); // 以读写模式打开块文件
if (fd < 0) { // 如果打开失败,记录错误并返回
LOG(ERROR) << "Open file failed: " << chunkpath;
return false;
}
// 根据是否只标记清洁,执行实际的清洁操作或仅标记文件
// ... 清洁操作代码 ...
// 将清洁后的块移动到清洁列表中
std::string targetpath = chunkpath + kCleanChunkSuffix_; // 添加清洁后缀
if (fsptr_->Rename(chunkpath, targetpath) < 0) { // 重命名文件,标记为清洁
LOG(ERROR) << "Rename file failed: " << chunkpath;
return false;
}
return true; // 清洁成功
}
// FilePool类的清洁线程工作方法,定期执行清洁操作
void FilePool::CleanWorker() {
// 清洁线程逻辑,包括检查条件、执行清洁操作、记录日志等
// ... 清洁线程工作代码 ...
}
// FilePool类的启动清洁线程方法
bool FilePool::StartCleaning() {
if (poolOpt_.needClean && !cleanAlived_.exchange(true)) { // 如果需要清洁且清洁线程未运行
// 初始化清洁线程并启动
// ... 线程启动代码 ...
LOG(INFO) << "Start clean thread ok.";
}
return true; // 启动成功
}
// FilePool类的停止清洁线程方法
bool FilePool::StopCleaning() {
if (cleanAlived_.exchange(false)) { // 如果清洁线程正在运行
// 停止清洁线程并等待线程结束
// ... 线程停止代码 ...
LOG(INFO) << "Stop clean thread ok.";
}
return true; // 停止成功
}
// FilePool类的获取块方法,用于从文件池中获取或创建新的块
bool FilePool::GetChunk(bool needClean, uint64_t* chunkid, bool* isCleaned) {
// 获取块逻辑,包括从脏块列表或清洁块列表中获取块,或创建新块
// ... 获取块代码 ...
return true; // 获取成功
}
// FilePool类的获取文件方法,用于创建新文件并写入元数据页
int FilePool::GetFile(const string& targetpath, char* metapage, bool needClean) {
// 创建文件逻辑,包括尝试重命名以创建新文件,写入元数据页,处理重试等
// ... 创建文件代码 ...
return 0; // 成功返回0
}
// FilePool类的回收文件方法,用于回收不再需要的块文件
int FilePool::RecycleFile(const string& chunkpath) {
// 回收文件逻辑,包括检查文件大小,重命名文件以回收,处理错误等
// ... 回收文件代码 ...
return 0; // 成功返回0
}
// FilePool类的析构函数,清理资源
FilePool::~FilePool() {
// 清理文件池资源,包括关闭文件描述符,释放内存等
// ... 清理资源代码 ...
}
// FilePool类的其他辅助方法,用于文件池的管理和操作
// ... 其他方法代码 ...
FilePool
类管理了一个用于存储块文件的池子。它提供了初始化、清洁、启动/停止清洁线程、获取/回收块文件等方法。这些方法通过与底层文件系统的交互来维护文件池的状态,确保数据块的有效管理和回收。通过这些方法,FilePool
类能够支持高效的数据块存储和重用,优化存储资源的使用。