#include "message_bus/pipeline/PipelineEngine.h" #include #include #include #include #include #include "message_bus/pipeline/stages/1_framers/ModbusRtuFraming.h" #include "utils/logs/logging.h" namespace softbus::message_bus::pipeline { struct EndpointFramingState { softbus::core::memory::LockFreeQueue chunkQ; std::atomic running{true}; std::thread th; std::uint64_t nextSeq{1}; QString endpoint; std::shared_ptr pool; softbus::message_bus::pipeline::stages::framers::ModbusRtuFramerConfig modbusCfg; std::shared_ptr pass; std::function pushFramed; explicit EndpointFramingState(std::size_t cap) : chunkQ(cap) { } }; namespace { void endpointFramerThread(std::shared_ptr st) { using softbus::message_bus::pipeline::stages::framers::ModbusRtuFramer; using softbus::message_bus::pipeline::stages::framers::protocolHintIsModbusRtu; auto modbus = std::make_unique(st->pool, st->modbusCfg, st->endpoint); while (st->running.load(std::memory_order_acquire)) { PipelineContext ch; if (!st->chunkQ.pop(ch)) { std::this_thread::sleep_for(std::chrono::milliseconds(1)); continue; } std::vector out; if (protocolHintIsModbusRtu(ch.protocolHint)) { modbus->feed(ch, out); } else if (st->pass) { st->pass->feed(ch, out); } for (auto& x : out) { x.frameSeq = st->nextSeq++; if (st->pushFramed) { st->pushFramed(std::move(x)); } } } } } // namespace PipelineEngine::PipelineEngine(std::size_t queueCapacity) : m_ingressQ(queueCapacity) , m_egressQ(queueCapacity) { } PipelineEngine::~PipelineEngine() { stop(); } void PipelineEngine::setMemoryPool(std::shared_ptr pool) { m_pool = std::move(pool); } void PipelineEngine::setRuntimeConfig(PipelineRuntimeConfig cfg) { m_rtConfig = cfg; } void PipelineEngine::loadRuntimeConfigFromJson(const QJsonObject& obj) { if (obj.isEmpty()) { LOG_ERROR() << "PipelineEngine: runtime config is empty"; // return; } m_rtConfig.parallelPipeline = obj.value(QStringLiteral("parallelPipeline")).toBool(true); m_rtConfig.parseWorkerCount = std::max(1, obj.value(QStringLiteral("parseWorkerCount")).toInt(2)); m_rtConfig.orderedEgress = obj.value(QStringLiteral("orderedEgress")).toBool(true); m_rtConfig.framedQueueMax = static_cast( std::max(64, obj.value(QStringLiteral("framedQueueMax")).toInt(4096))); m_rtConfig.maxReorderDepth = static_cast( std::max(16, obj.value(QStringLiteral("maxReorderDepth")).toInt(256))); m_rtConfig.modbus.maxAdu = static_cast( std::max(8, obj.value(QStringLiteral("modbusRtuMaxFrameBytes")).toInt(256))); m_rtConfig.modbus.interFrameTimeoutMs = obj.value(QStringLiteral("modbusRtuInterFrameTimeoutMs")).toInt(0); } void PipelineEngine::start() { if (m_running.exchange(true)) { return; } if (!m_pool) { LOG_ERROR() << "PipelineEngine::start: memory pool not set"; m_running = false; return; } m_modbusFramer = std::make_unique(m_pool, m_rtConfig.modbus, QString{}); m_passthroughFramer = std::make_shared(m_pool); // 如果启用并行管道 则创建帧队列和解析线程 如果启用有序出口 则创建合并队列和合并线程 // 并行管道是用来处理多个端点的数据流的 // 有序出口是用来保证数据流的有序性的 // 帧队列是用来存储帧的 // 解析线程是用来处理帧的 // 合并队列是用来存储合并的帧的 // 合并线程是用来处理合并的帧的 if (m_rtConfig.parallelPipeline) { m_framedQ = std::make_unique>( m_rtConfig.framedQueueMax); for (int i = 0; i < m_rtConfig.parseWorkerCount; ++i) { m_parseThreads.emplace_back([this]() { parseWorkerLoop(); }); } if (m_rtConfig.orderedEgress) { m_mergeQ = std::make_unique>(0); m_mergerThread = std::thread([this]() { mergerLoop(); }); } } else { m_worker = std::thread([this]() { runSingleWorker(); }); } } void PipelineEngine::stop() { if (!m_running.exchange(false)) { return; } { std::lock_guard lk(m_endpointMutex); for (auto it = m_endpointFramers.constBegin(); it != m_endpointFramers.constEnd(); ++it) { if (it.value()) { it.value()->running.store(false, std::memory_order_release); } } for (auto it = m_endpointFramers.constBegin(); it != m_endpointFramers.constEnd(); ++it) { if (it.value() && it.value()->th.joinable()) { it.value()->th.join(); } } m_endpointFramers.clear(); } if (m_worker.joinable()) { m_worker.join(); } for (auto& t : m_parseThreads) { if (t.joinable()) { t.join(); } } m_parseThreads.clear(); if (m_mergerThread.joinable()) { m_mergerThread.join(); } m_framedQ.reset(); m_mergeQ.reset(); m_modbusFramer.reset(); m_passthroughFramer.reset(); } // 功能 :清空 ingress 队列 // 参数 :无 // 返回值 :无 // 逻辑 :从 ingress 队列中取出数据 直到队列为空 void PipelineEngine::drain() { PipelineContext tmp; while (m_ingressQ.pop(tmp)) { } } // 功能 :将数据推送到 ingress 队列 // 参数 :ctx 数据 // 返回值 :是否成功 // 逻辑 :如果并行管道启用 则根据端点确保帧解析器 然后推送到帧队列 如果并行管道未启用 则直接推送到 ingress 队列 bool PipelineEngine::enqueueIngress(PipelineContext ctx) { if (m_rtConfig.parallelPipeline) { if (ctx.endpoint.isEmpty()) { ++m_counters.drop; return false; } ensureEndpointFramer(ctx.endpoint); std::shared_ptr st; { std::lock_guard lk(m_endpointMutex); st = m_endpointFramers.value(ctx.endpoint); } if (!st || !st->chunkQ.push(std::move(ctx))) { ++m_counters.drop; return false; } ++m_counters.in; return true; } if (!m_ingressQ.push(std::move(ctx))) { ++m_counters.drop; return false; } ++m_counters.in; return true; } // 功能 :将数据推送到 egress 队列 // 参数 :ctx 数据 // 返回值 :是否成功 // 逻辑 :将数据推送到 egress 队列 bool PipelineEngine::enqueueEgress(PipelineContext ctx) { return m_egressQ.push(std::move(ctx)); } // 功能 :尝试从 egress 队列中取出数据 // 参数 :out 数据 // 返回值 :是否成功 // 逻辑 :从 egress 队列中取出数据 如果队列为空 则返回false 如果队列不为空 则返回true bool PipelineEngine::tryPopEgress(PipelineContext& out) { return m_egressQ.pop(out); } // 功能 :设置插件管理器 // 参数 :pluginManager 插件管理器 // 返回值 :无 // 逻辑 :设置插件管理器 void PipelineEngine::setPluginManager(std::shared_ptr pluginManager) { m_pluginManager = std::move(pluginManager); } // 功能 :确保端点帧解析器 // 参数 :endpoint 端点 // 返回值 :无 // 逻辑 :如果端点帧解析器不存在 则创建端点帧解析器 void PipelineEngine::ensureEndpointFramer(const QString& endpoint) { std::lock_guard lk(m_endpointMutex); if (m_endpointFramers.contains(endpoint)) { return; } const std::size_t qcap = m_ingressQ.capacity(); auto st = std::make_shared(qcap > 0 ? qcap : 4096); st->endpoint = endpoint; st->pool = m_pool; st->modbusCfg = m_rtConfig.modbus; st->pass = m_passthroughFramer; st->pushFramed = [this](PipelineContext c) { if (!m_framedQ) { return; } if (!m_framedQ->tryPush(std::move(c))) { ++m_counters.drop; LOG_WARNING() << "PipelineEngine: framed queue full drop"; } }; st->th = std::thread(endpointFramerThread, st); m_endpointFramers.insert(endpoint, std::move(st)); } // 功能 :分发帧解析器 // 参数 :chunkIn 数据 // 返回值 :无 // 逻辑 :根据协议提示 选择合适的帧解析器 进行帧解析 void PipelineEngine::dispatchFramer(PipelineContext& chunkIn, std::vector& completeFramesOut) { using softbus::message_bus::pipeline::stages::framers::protocolHintIsModbusRtu; // 根据协议提示 选择合适的帧解析器 进行帧解析 if (protocolHintIsModbusRtu(chunkIn.protocolHint)) { if (m_modbusFramer) { m_modbusFramer->feed(chunkIn, completeFramesOut); } } else if (m_passthroughFramer) { m_passthroughFramer->feed(chunkIn, completeFramesOut); } } // 功能 :分配帧序列号 void PipelineEngine::assignFrameSequence(PipelineContext& ctx) { std::lock_guard lk(m_seqMutex); ctx.frameSeq = ++m_nextFrameSeqByEndpoint[ctx.endpoint]; } void PipelineEngine::runSingleWorker() { // 单线程工作线程 从 ingress 队列中取出数据 进行处理 然后推送到 egress 队列中 while (m_running.load(std::memory_order_acquire)) { PipelineContext ctx; if (!m_ingressQ.pop(ctx)) { std::this_thread::sleep_for(std::chrono::milliseconds(1)); continue; } std::vector batch; dispatchFramer(ctx, batch); for (auto& c : batch) { if (c.frameKind != FrameKind::CompleteFrame) { continue; } // std::ostringstream oss; oss << std::hex << std::setfill('0'); for (std::size_t i = 0; i < c.payload.block->size; ++i) { oss << std::setw(2) << static_cast(c.payload.block->data[i]); if (i + 1 < c.payload.block->size) { oss << ' '; } } const QString hexPreview = QString::fromStdString(oss.str()); LOG_INFO() << "the data is"<< hexPreview; // 分配帧序列号 assignFrameSequence(c); if (!runStages234(c)) { ++m_counters.error; continue; } if (!m_egressQ.push(std::move(c))) { ++m_counters.drop; continue; } ++m_counters.out; } } } void PipelineEngine::parseWorkerLoop() { while (true) { PipelineContext ctx; const bool have = m_framedQ && m_framedQ->popWaitFor(ctx, m_running, std::chrono::milliseconds(50)); // 从帧队列中取出帧 , 如果帧队列为空 则等待50毫秒 if (!have) { if (!m_running.load(std::memory_order_acquire)) { break; } continue; } std::ostringstream oss; oss << std::hex << std::setfill('0'); for (std::size_t i = 0; i < ctx.payload.block->size; ++i) { oss << std::setw(2) << static_cast(ctx.payload.block->data[i]); if (i + 1 < ctx.payload.block->size) { oss << ' '; } } const QString hexPreview = QString::fromStdString(oss.str()); LOG_INFO() << "the data is"<< hexPreview; const bool ok = runStages234(ctx); if (m_rtConfig.orderedEgress && m_mergeQ) { MergeItem it; it.endpoint = ctx.endpoint; it.seq = ctx.frameSeq; it.pipelineOk = ok; it.ctx = std::move(ctx); m_mergeQ->push(std::move(it)); } else { if (!ok) { ++m_counters.error; continue; } if (!m_egressQ.push(std::move(ctx))) { ++m_counters.drop; continue; } ++m_counters.out; } } } void PipelineEngine::mergerLoop() { while (true) { MergeItem it; const bool have = m_mergeQ && m_mergeQ->popWaitFor(it, m_running, std::chrono::milliseconds(50)); if (!have) { if (!m_running.load(std::memory_order_acquire)) { break; } continue; } ingestMergeItem(std::move(it)); } } // 功能 :合并帧 // 参数 :item 合并项 // 返回值 :无 // 逻辑 :将合并项中的数据推送到 egress 队列中 void PipelineEngine::ingestMergeItem(MergeItem item) { std::lock_guard lk(m_mergeStateMutex); auto& st = m_mergeByEndpoint[item.endpoint]; if (m_rtConfig.maxReorderDepth > 0 && static_cast(st.buffer.size()) >= m_rtConfig.maxReorderDepth) { ++m_counters.mergeDrop; LOG_WARNING() << "PipelineEngine: merge reorder depth exceeded endpoint=" << item.endpoint; return; } st.buffer.insert(item.seq, std::make_pair(std::move(item.ctx), item.pipelineOk)); while (st.buffer.contains(st.nextExpected)) { auto pr = st.buffer.take(st.nextExpected); ++st.nextExpected; const bool pipelineOk = pr.second; PipelineContext ctx = std::move(pr.first); if (!pipelineOk) { ++m_counters.error; continue; } if (!m_egressQ.push(std::move(ctx))) { ++m_counters.drop; continue; } ++m_counters.out; } } // 功能 :运行阶段234 // 参数 :ctx 数据 // 返回值 :是否成功 // 逻辑 :如果帧类型不是完整帧 则返回false 如果阶段2解析失败 则返回false 如果阶段3过滤失败 则返回false 如果阶段4验证失败 则返回false 如果都成功 则返回true bool PipelineEngine::runStages234(PipelineContext& ctx) { if (ctx.frameKind != FrameKind::CompleteFrame) { return false; } if (!stage2Parser(ctx)) { return false; } if (!stage3Filter(ctx)) { return false; } if (!stage4Validator(ctx)) { return false; } return true; } // 功能 :验证阶段4 // 参数 :ctx 数据 // 返回值 :是否成功 // 逻辑 :如果有效载荷无效 则返回false 如果都成功 则返回true bool PipelineEngine::stage4Validator(PipelineContext& ctx) { if (!ctx.payload.valid()) { return false; } if (ctx.endpoint.isEmpty()) { return false; } if (!ctx.timestamp.isValid()) { ctx.timestamp = QDateTime::currentDateTimeUtc(); } if (ctx.frameKind != FrameKind::CompleteFrame) { return false; } return true; } // 功能 :运行阶段2解析器 // 参数 :ctx 数据 // 返回值 :是否成功 // 逻辑 :如果插件管理器为空 则返回true 如果插件管理器不为空 则选择合适的插件 创建会话 如果会话为空 则返回false 如果会话不为空 则返回true bool PipelineEngine::stage2Parser(PipelineContext& ctx) { if (!m_pluginManager) { return true; } auto plugin = m_pluginManager->selectProtocolPlugin(ctx.protocolHint); if (!plugin) { return true; } auto session = plugin->createSession(); if (!session) { return false; } return session->feed(ctx); } bool PipelineEngine::stage3Filter(PipelineContext& ctx) { (void)ctx; return true; } } // namespace softbus::message_bus::pipeline