#include "message_bus/pipeline/PipelineEngine.h" #include #include #include #include #include #include "plugins/protocols/modbusrtu/framer/ModbusRtuFraming.h" #include "plugins/protocols/modbusrtu/framer/ModbusRtuFramerPlugin.h" #include "message_bus/pipeline/stages/3_filters/ProtocolParseFilter.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; std::function&)> feed; std::function pushFramed; explicit EndpointFramingState(std::size_t cap) : chunkQ(cap) { } }; namespace { void endpointFramerThread(std::shared_ptr st) { 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 (st->feed) { st->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.modbusMaxAdu = static_cast( std::max(8, obj.value(QStringLiteral("modbusRtuMaxFrameBytes")).toInt(256))); m_rtConfig.modbusInterFrameTimeoutMs = 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_passthroughFramer = std::make_shared(m_pool); if (m_pluginManager) { softbus::message_bus::pipeline::protocol::modbusrtu::ModbusRtuFramerPluginConfig cfg; cfg.maxAdu = m_rtConfig.modbusMaxAdu; cfg.interFrameTimeoutMs = m_rtConfig.modbusInterFrameTimeoutMs; m_pluginManager->registerProtocolFramerPlugin( softbus::message_bus::pipeline::protocol::modbusrtu::makeModbusRtuFramerPlugin(m_pool, cfg)); } // 如果启用并行管道 则创建帧队列和解析线程 如果启用有序出口 则创建合并队列和合并线程 // 并行管道是用来处理多个端点的数据流的 // 有序出口是用来保证数据流的有序性的 // 帧队列是用来存储帧的 // 解析线程是用来处理帧的 // 合并队列是用来存储合并的帧的 // 合并线程是用来处理合并的帧的 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_passthroughFramer.reset(); { std::lock_guard lk(m_framerSessionMutex); m_framerSessions.clear(); } } // 功能 :清空 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->feed = [this](PipelineContext& in, std::vector& out) { this->dispatchFramer(in, out); }; 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) { if (m_pluginManager) { auto plugin = m_pluginManager->selectProtocolFramerPlugin(chunkIn.protocolHint); if (plugin) { plugin->bindMemoryPool(m_pool); const QString key = chunkIn.endpoint + QStringLiteral("|") + plugin->pluginId(); std::lock_guard lk(m_framerSessionMutex); auto it = m_framerSessions.find(key); if (it == m_framerSessions.end() || !it.value()) { QJsonObject params; params.insert(QStringLiteral("modbusRtuMaxFrameBytes"), static_cast(m_rtConfig.modbusMaxAdu)); params.insert(QStringLiteral("modbusRtuInterFrameTimeoutMs"), m_rtConfig.modbusInterFrameTimeoutMs); auto s = plugin->createFramerSession(chunkIn.endpoint, params); m_framerSessions.insert( key, s ? std::shared_ptr(std::move(s)) : nullptr); it = m_framerSessions.find(key); } if (it != m_framerSessions.end() && it.value()) { it.value()->feedChunk(chunkIn, completeFramesOut); return; } } } 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; } 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; } 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; LOG_INFO() << "the protocol hint is"<< ctx.protocolHint; const QString directionText = (ctx.direction == BusDirection::Upstream) ? QStringLiteral("Upstream") : (ctx.direction == BusDirection::Downstream) ? QStringLiteral("Downstream") : QStringLiteral("Unknown"); LOG_INFO() << "the direction is" << directionText; if (!stage2Parser(ctx)) { return false; } QJsonObject parsed = ctx.parsed; LOG_INFO() << "the parsed is"<< parsed; softbus::message_bus::pipeline::protocol::ProtocolEnvelope protocol = ctx.protocol; if (const auto* modbusPdu = std::get_if(&protocol.pdu)) { LOG_INFO() << "the protocol text is" << softbus::message_bus::pipeline::protocol::toText(*modbusPdu); } else { LOG_INFO() << "the protocol text is" << QStringLiteral("ProtocolEnvelopePdu::monostate"); } // @TODO 以后需要测试是否丢包和解析延迟 // m_count++; // LOG_INFO() << "the count of command is" << m_count; 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) { static softbus::message_bus::pipeline::stages::filters::ProtocolParseFilter s_filter; return s_filter.apply(ctx); } } // namespace softbus::message_bus::pipeline