源码路径
curve-release2.2\src\chunkserver\concurrent_apply
以下是对concurrent_apply.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 <glog/logging.h> // 用于日志记录
#include <algorithm> // 用于算法支持
#include <vector> // 用于动态数组
#include "src/chunkserver/concurrent_apply/concurrent_apply.h" // 引入并发应用模块的头文件
#include "src/common/concurrent/count_down_event.h" // 用于倒计时事件
using ::curve::common::CountDownEvent; // 使用CountDownEvent
namespace curve {
namespace chunkserver {
namespace concurrent {
// ConcurrentApplyModule类的初始化方法
bool ConcurrentApplyModule::Init(const ConcurrentApplyOption &opt) {
// 如果并发模块已经启动,则记录警告并返回
if (start_) {
LOG(WARNING) << "concurrent module already start!";
return true;
}
// 检查并发选项参数是否有效,并进行初始化
if (false == checkOptAndInit(opt)) {
return false;
}
// 设置启动标志为true
start_ = true;
// 初始化条件变量,用于等待线程池初始化完成
cond_.Reset(opt.rconcurrentsize + opt.wconcurrentsize);
// 初始化读取并发线程池
InitThreadPool(ThreadPoolType::READ, rconcurrentsize_, rqueuedepth_);
// 初始化写入并发线程池
InitThreadPool(ThreadPoolType::WRITE, wconcurrentsize_, wqueuedepth_);
// 等待线程池初始化完成,超时时间为5000毫秒
if (!cond_.WaitFor(5000)) {
LOG(ERROR) << "init concurrent module's threads fail";
start_ = false; // 重置启动标志
}
// 记录线程池初始化成功的日志
LOG(INFO) << "Init concurrent module's threads success";
return start_; // 返回启动状态
}
// 检查并发选项参数并进行初始化的方法
bool ConcurrentApplyModule::checkOptAndInit(const ConcurrentApplyOption &opt) {
// 检查参数是否满足条件,即是否大于0
if (opt.rconcurrentsize <= 0 || opt.wconcurrentsize <= 0 ||
opt.rqueuedepth <= 0 || opt.wqueuedepth <= 0) {
// 如果参数不满足条件,记录日志并返回失败
LOG(INFO) << "init concurrent module fail, params must >=0"
<< ", rconcurrentsize=" << opt.rconcurrentsize
<< ", wconcurrentsize=" << opt.wconcurrentsize
<< ", rqueuedepth=" << opt.rqueuedepth
<< ", wqueuedepth=" << opt.wqueuedepth;
return false;
}
// 更新成员变量以保存读取和写入的并发大小及队列深度
wconcurrentsize_ = opt.wconcurrentsize;
wqueuedepth_ = opt.wqueuedepth;
rconcurrentsize_ = opt.rconcurrentsize;
rqueuedepth_ = opt.rqueuedepth;
return true; // 返回成功
}
// 初始化线程池的方法
void ConcurrentApplyModule::InitThreadPool(ThreadPoolType type, int concorrent, int depth) {
// 为每个并发线程创建一个任务线程
for (int i = 0; i < concorrent; i++) {
auto asyncth = new (std::nothrow) taskthread(depth); // 创建任务线程
CHECK(asyncth != nullptr) << "allocate failed!"; // 检查分配是否成功
// 根据线程池类型,将任务线程添加到对应的映射中
switch (type) {
case ThreadPoolType::READ:
rapplyMap_.insert(std::make_pair(i, asyncth)); // 添加到读取线程池映射
break;
case ThreadPoolType::WRITE:
wapplyMap_.insert(std::make_pair(i, asyncth)); // 添加到写入线程池映射
break;
}
}
// 为每个任务线程创建一个线程,并启动它们
for (int i = 0; i < concorrent; i++) {
switch (type) {
case ThreadPoolType::READ:
rapplyMap_[i]-eth = std::thread(&ConcurrentApplyModule::Run, this, type, i); // 创建读取线程
break;
case ThreadPoolType::WRITE:
wapplyMap_[i]-eth = std::thread(&ConcurrentApplyModule::Run, this, type, i); // 创建写入线程
break;
}
}
}
// 运行线程池中的任务的方法
void ConcurrentApplyModule::Run(ThreadPoolType type, int index) {
// 通知条件变量,表示线程池中的线程已启动
cond_.Signal();
// 循环运行,直到停止标志被设置为false
while (start_) {
// 根据线程池类型,从对应的队列中弹出任务并执行
switch (type) {
case ThreadPoolType::READ:
rapplyMap_[index]->tq.Pop(); // 执行读取任务
break;
case ThreadPoolType::WRITE:
wapplyMap_[index]->tq.Pop(); // 执行写入任务
break;
}
}
}
// 停止并发应用模块的方法
void ConcurrentApplyModule::Stop() {
// 记录停止并发应用模块的日志
LOG(INFO) << "stop ConcurrentApplyModule...";
// 设置停止标志为false
start_ = false;
// 定义唤醒函数,用于唤醒等待的任务
auto wakeup = []() {};
// 遍历读取线程池映射,并停止所有读取线程
for (auto iter : rapplyMap_) {
iter.second->tq.Push(wakeup); // 推送唤醒任务到队列
iter.second->eth.join(); // 等待线程结束
delete iter.second; // 删除任务线程
}
rapplyMap_.clear(); // 清空读取线程池映射
// 遍历写入线程池映射,并停止所有写入线程
for (auto iter : wapplyMap_) {
iter.second->tq.Push(wakeup); // 推送唤醒任务到队列
iter.second->eth.join(); // 等待线程结束
delete iter.second; // 删除任务线程
}
wapplyMap_.clear(); // 清空写入线程池映射
// 记录停止并发应用模块成功的日志
LOG(INFO) << "stop ConcurrentApplyModule ok.";
}
// 清空并发应用模块中所有任务的方法
void ConcurrentApplyModule::Flush() {
// 创建倒计时事件,用于等待所有写入线程完成任务
CountDownEvent event(wconcurrentsize_);
// 定义刷新任务,用于清空队列
auto flushtask = [&event]() {
event.Signal(); // 触发事件以唤醒等待的线程
};
// 遍历写入线程池映射,并向每个队列推送刷新任务
for (int i = 0; i < wconcurrentsize_; i++) {
wapplyMap_[i]->tq.Push(flushtask); // 推送刷新任务
}
// 等待所有写入线程完成任务
event.Wait();
}
// 根据操作类型调度任务到相应的线程池的方法
ThreadPoolType ConcurrentApplyModule::Schedule(CHUNK_OP_TYPE optype) {
// 根据操作类型返回相应的线程池类型
switch (optype) {
case CHUNK_OP_READ:
case CHUNK_OP_RECOVER:
return ThreadPoolType::READ; // 读取操作使用读取线程池
default:
return ThreadPoolType::WRITE; // 其他操作使用写入线程池
}
}
} // namespace concurrent
} // namespace chunkserver
} // namespace curve
这段代码定义了一个ConcurrentApplyModule
类,它用于管理和执行并发任务。类中包含了初始化、停止、清空任务、调度任务以及运行任务的方法。
Init
方法用于初始化并发模块,包括检查参数的有效性、初始化读取和写入线程池,并等待线程池初始化完成。
checkOptAndInit
方法用于检查并发选项参数是否有效,并更新成员变量以保存读取和写入的并发大小及队列深度。
InitThreadPool
方法用于初始化指定类型的线程池,为每个并发