endpointhash

This commit is contained in:
flower_linux
2026-04-15 20:05:04 +08:00
parent 94eec643de
commit 11bd86063d
21 changed files with 314 additions and 157 deletions

Binary file not shown.

View File

@@ -4,7 +4,7 @@
- **物理设备**:真实硬件端口(当前主要是串口),由 `SerialQtDriver` 直接读写。
- **设备实例**`SerialDevice`,负责单设备生命周期、驱动回调、上下行数据接入。
- **原始总线消息**`RawBusMessage`,包含 `endpoint``protocolHint``payload``traceId``direction` 等基础字段。
- **原始总线消息**`RawBusMessage`,包含 `endpointHash``protocol``routingKey``header``payload``traceId``direction` 等基础字段。
- **流水线上下文**`PipelineContext`,继承 `RawBusMessage`,增加 `frameKind``frameSeq` 等管道字段。
- **业务消息**:经过协议解析和映射后得到 `DOMMessage`(统一语义数据)。
@@ -30,10 +30,12 @@
1.`MemoryPool` 分配内存块并拷贝原始字节。
2. 构造 `RawBusMessage`
- `direction = Upstream`
- `endpoint = 串口名`
- `protocolHint = DeviceInfo.protocol`
- `payload/payloadSize = 原始字节数据`
- `traceId = serial:<endpoint>:<timestamp>`
- `endpointHash = makeEndpointHash(串口名)`
- `protocol = protocolTypeFromHint(DeviceInfo.protocol)`
- `routingKey = makeRoutingKey(endpointHash, deviceId)`
- `header = ProtocolHeader{}`(由后续 framer/parser 按协议填充 OOB 元数据)
- `payload = 原始字节数据`(长度由 `payload.length` 表示,不再维护 `payloadSize`
- `traceId = serial:<endpoint>:<timestampMs>`
3. 调用 `m_ingress->push(std::move(ctx))` 进入统一入口。
4. 若内存池不足或 ingress 队列满,通过 `reportError(...)` 记录错误。
@@ -54,7 +56,7 @@
`enqueueIngress(...)` 分两种模式:
- **并行模式parallelPipeline=true**
-`endpoint` 创建/复用独立 `EndpointFramingState`(每端点一个分帧线程 + chunk 队列)。
-`endpointHash` 创建/复用独立 `EndpointFramingState`(每端点一个分帧线程 + chunk 队列)。
- chunk 先进入端点队列,端点线程负责分帧并赋值 `frameSeq`
- 完整帧进入 `m_framedQ`,由解析线程池处理。
- **单线程模式parallelPipeline=false**
@@ -64,9 +66,10 @@
`dispatchFramer(...)` 的选择策略:
1. 优先根据 `protocolHint` 从插件管理器选择协议分帧插件。
2. `endpoint + pluginId` 复用 framer session保持协议状态机连续性
1. `protocol``ProtocolType`从插件管理器选择协议分帧插件。
2.结构化键 `SessionKey{endpointHash, pluginId}` 复用 framer/parser/mapper session保持协议状态机连续性
3. 若没有可用插件,降级到 `PassthroughFramer`(透传/整包策略)。
4. framer session 创建接口已升级为 `createFramerSession(uint32_t endpointHash, ...)`,不再传递 endpoint 字符串。
输出:`frameKind = CompleteFrame` 的帧批次。
@@ -84,6 +87,7 @@
- 最低校验当前为 `messageId` 非空。
4. **Transform/Enrich**
- 仅对通过 filter+validator 的 `DOMMessage` 应用动态规则scale/offset/unit
- 规则作用域按 `endpointHash/deviceId/stableKey` 匹配,不再按 endpoint 字符串匹配。
- 写入 trace补充富化字段。
说明(与代码一致):
@@ -96,7 +100,7 @@
- 未开启有序出口:解析成功后直接进入 `m_egressQ`
- 开启 `orderedEgress`
- 解析线程先写入 `m_mergeQ`
- `mergerLoop``endpoint + frameSeq` 重排。
- `mergerLoop``endpointHash(映射键) + frameSeq` 重排。
- 使用 `nextExpected` 保证同端点有序输出。
- 超过 `maxReorderDepth` 的乱序缓存上限会丢弃并计数。
@@ -138,7 +142,7 @@ SerialQtDriver(read callback)
## 6. egress 到设备(现状)
- `DeviceBusManager` 已启动 `processEgressLoop`,持续从 `PipelineEngine::tryPopEgress` 取数据并调用 `EgressRouter::send`
- `EgressRouter` 已实现 `endpoint -> SerialDevice` 查找和 `writePayload(...)` 发送。
- `EgressRouter` 已实现基于 `endpointHash``SerialDevice` 查找和 `writePayload(...)` 发送。
- 当前关键缺口:`SerialDeviceManager::initializeSerialDeviceWithDeps``bindSerialDevice(...)` 仍被注释,导致路由表通常为空,`send` 多数返回失败。
- 因此当前链路是“egress 框架已存在,但默认没有绑定到串口实例”。

View File

@@ -17,10 +17,10 @@ class ModbusRtuFramerSession final : public softbus::core::plugin_system::IProto
public:
ModbusRtuFramerSession(std::shared_ptr<softbus::core::memory::MemoryPool> pool,
ModbusRtuFramerPluginConfig cfg,
QString endpoint)
std::uint32_t endpointHash)
: m_pool(std::move(pool))
, m_cfg(cfg)
, m_endpoint(std::move(endpoint))
, m_endpointHash(endpointHash)
{
m_buf.resize(m_cfg.maxAdu);
}
@@ -32,7 +32,7 @@ public:
return;
}
const std::uint8_t* p = in.payload.bytes();
const std::size_t n = in.payloadSize ? in.payloadSize : in.payload.length;
const std::size_t n = in.payload.length;
if (!p || n == 0) {
return;
}
@@ -47,7 +47,8 @@ public:
m_lastActivity = m_lastRx;
if (m_len + n > m_cfg.maxAdu) {
LOG_WARNING() << "ModbusRtuFramerPlugin: overflow endpoint=" << m_endpoint;
LOG_WARNING() << "ModbusRtuFramerPlugin: overflow endpointHash=0x"
<< QString::number(m_endpointHash, 16);
m_len = 0;
return;
}
@@ -78,16 +79,22 @@ public:
softbus::core::models::RawBusMessage framed;
framed.deviceId = in.deviceId;
framed.stableKey = in.stableKey;
framed.endpoint = in.endpoint;
framed.timestamp = in.timestamp;
framed.protocolHint = in.protocolHint;
framed.endpointHash = in.endpointHash;
framed.protocol = softbus::core::models::ProtocolType::MODBUS_RTU;
framed.logicalAddress = in.logicalAddress;
framed.routingKey = in.routingKey;
framed.header = in.header;
framed.timestampMs = in.timestampMs;
framed.traceId = in.traceId;
framed.direction = in.direction;
framed.payload.block = std::move(blk);
framed.payload.offset = 0;
framed.payload.length = *pred;
framed.payloadSize = *pred;
if (*pred >= 2 && framed.payload.block && framed.payload.block->data) {
framed.header.modbus.slaveId = framed.payload.block->data[0];
framed.header.modbus.functionCode = framed.payload.block->data[1];
framed.logicalAddress = framed.header.modbus.slaveId;
}
out.push_back(std::move(framed));
const std::size_t rest = m_len - *pred;
@@ -98,7 +105,6 @@ public:
}
in.payload = {};
in.payloadSize = 0;
}
void reset() override { m_len = 0; }
@@ -107,7 +113,7 @@ public:
private:
std::shared_ptr<softbus::core::memory::MemoryPool> m_pool;
ModbusRtuFramerPluginConfig m_cfg;
QString m_endpoint;
std::uint32_t m_endpointHash{0};
std::vector<std::uint8_t> m_buf;
std::size_t m_len{0};
std::chrono::steady_clock::time_point m_lastRx{std::chrono::steady_clock::now()};
@@ -128,9 +134,9 @@ QString ModbusRtuFramerPlugin::pluginId() const
return QStringLiteral("modbus_rtu_framer");
}
bool ModbusRtuFramerPlugin::supports(const QString& protocolHint) const
softbus::core::models::ProtocolType ModbusRtuFramerPlugin::protocolType() const
{
return isModbusRtuHint(protocolHint);
return softbus::core::models::ProtocolType::MODBUS_RTU;
}
void ModbusRtuFramerPlugin::bindMemoryPool(std::shared_ptr<softbus::core::memory::MemoryPool> pool)
@@ -139,7 +145,7 @@ void ModbusRtuFramerPlugin::bindMemoryPool(std::shared_ptr<softbus::core::memory
}
std::unique_ptr<softbus::core::plugin_system::IProtocolFramerSession>
ModbusRtuFramerPlugin::createFramerSession(const QString& endpoint, const QJsonObject& params)
ModbusRtuFramerPlugin::createFramerSession(std::uint32_t endpointHash, const QJsonObject& params)
{
if (!m_pool) {
return {};
@@ -152,7 +158,7 @@ ModbusRtuFramerPlugin::createFramerSession(const QString& endpoint, const QJsonO
if (params.contains(QStringLiteral("modbusRtuInterFrameTimeoutMs"))) {
cfg.interFrameTimeoutMs = params.value(QStringLiteral("modbusRtuInterFrameTimeoutMs")).toInt(cfg.interFrameTimeoutMs);
}
return std::make_unique<ModbusRtuFramerSession>(m_pool, cfg, endpoint);
return std::make_unique<ModbusRtuFramerSession>(m_pool, cfg, endpointHash);
}
std::shared_ptr<softbus::core::plugin_system::IProtocolFramerPlugin> makeModbusRtuFramerPlugin(

View File

@@ -27,10 +27,10 @@ public:
ModbusRtuFramerPluginConfig cfg = {});
QString pluginId() const override;
bool supports(const QString& protocolHint) const override;
softbus::core::models::ProtocolType protocolType() const override;
void bindMemoryPool(std::shared_ptr<softbus::core::memory::MemoryPool> pool) override;
std::unique_ptr<softbus::core::plugin_system::IProtocolFramerSession> createFramerSession(
const QString& endpoint, const QJsonObject& params) override;
std::uint32_t endpointHash, const QJsonObject& params) override;
private:
std::shared_ptr<softbus::core::memory::MemoryPool> m_pool;

View File

@@ -30,13 +30,14 @@ public:
for (int i = 0; i < resp->registers.size(); ++i) {
softbus::core::models::DOMMessage msg;
msg.messageId = QStringLiteral("%1.reg.%2")
.arg(rawContext.stableKey.isEmpty() ? QString::number(rawContext.deviceId)
: rawContext.stableKey)
.arg(rawContext.routingKey == 0
? QString::number(rawContext.deviceId)
: QString::number(rawContext.routingKey))
.arg(i);
msg.timestamp = rawContext.timestamp.toMSecsSinceEpoch();
msg.timestamp = rawContext.timestampMs;
msg.value = static_cast<std::uint32_t>(resp->registers[static_cast<qsizetype>(i)]);
msg.quality = softbus::core::models::DataQuality::GOOD;
msg.attributes.insert(QStringLiteral("sourceEndpoint"), rawContext.endpoint);
msg.attributes.insert(QStringLiteral("sourceEndpoint"), QString::number(rawContext.endpointHash));
out.push_back(std::move(msg));
}
return out;
@@ -46,12 +47,13 @@ public:
std::get_if<softbus::message_bus::pipeline::protocol::ReadHoldingRegistersRequest>(pdu)) {
softbus::core::models::DOMMessage msg;
msg.messageId = QStringLiteral("%1.req.read_holding")
.arg(rawContext.stableKey.isEmpty() ? QString::number(rawContext.deviceId)
: rawContext.stableKey);
msg.timestamp = rawContext.timestamp.toMSecsSinceEpoch();
.arg(rawContext.routingKey == 0
? QString::number(rawContext.deviceId)
: QString::number(rawContext.routingKey));
msg.timestamp = rawContext.timestampMs;
msg.value = static_cast<std::uint32_t>(req->quantity);
msg.quality = softbus::core::models::DataQuality::GOOD;
msg.attributes.insert(QStringLiteral("sourceEndpoint"), rawContext.endpoint);
msg.attributes.insert(QStringLiteral("sourceEndpoint"), QString::number(rawContext.endpointHash));
msg.attributes.insert(QStringLiteral("frameType"), QStringLiteral("request"));
msg.attributes.insert(QStringLiteral("startAddress"), static_cast<int>(req->startAddress));
msg.attributes.insert(QStringLiteral("quantity"), static_cast<int>(req->quantity));
@@ -67,9 +69,9 @@ class ModbusRtuProtocolMapperPlugin final : public softbus::core::plugin_system:
{
public:
QString pluginId() const override { return QStringLiteral("modbus_rtu_mapper"); }
bool supports(const QString& protocolHint) const override
softbus::core::models::ProtocolType protocolType() const override
{
return isModbusRtuHint(protocolHint);
return softbus::core::models::ProtocolType::MODBUS_RTU;
}
std::unique_ptr<softbus::core::plugin_system::IProtocolMapperSession> createMapperSession() override
{

View File

@@ -55,7 +55,7 @@ public:
if (!ctx.payload.valid()) {
return false;
}
const std::size_t n = ctx.payloadSize ? ctx.payloadSize : ctx.payload.length;
const std::size_t n = ctx.payload.length;
const std::uint8_t* p = ctx.payload.bytes();
if (!p || n < 4) {
return false;
@@ -86,9 +86,9 @@ class ModbusRtuProtocolPlugin final : public IProtocolPlugin
public:
QString pluginId() const override { return QStringLiteral("modbus_rtu"); }
bool supports(const QString& protocolHint) const override
softbus::core::models::ProtocolType protocolType() const override
{
return softbus::message_bus::pipeline::protocol::modbusrtu::isModbusRtuHint(protocolHint);
return softbus::core::models::ProtocolType::MODBUS_RTU;
}
std::unique_ptr<IProtocolSession> createSession() override

View File

@@ -11,7 +11,7 @@ namespace
softbus::message_bus::pipeline::RuleScope parseScope(const QJsonObject& params)
{
softbus::message_bus::pipeline::RuleScope scope;
scope.endpoint = params.value(QStringLiteral("endpoint")).toString();
scope.endpointHash = static_cast<std::uint32_t>(params.value(QStringLiteral("endpointHash")).toInteger(0));
scope.deviceId = params.value(QStringLiteral("deviceId")).toInt(-1);
scope.stableKey = params.value(QStringLiteral("stableKey")).toString();
return scope;

View File

@@ -0,0 +1,59 @@
#pragma once
#include <cstdint>
#include <QString>
#include "core/models/RawBusMessage.h"
namespace softbus::core::models
{
// Hash physical endpoint string into a compact routing key.
inline std::uint32_t makeEndpointHash(const QString& endpoint)
{
return qHash(endpoint);
}
// Build a deterministic string key from endpoint hash (for session maps).
inline QString makeEndpointKey(std::uint32_t endpointHash)
{
return QString::number(endpointHash, 16);
}
// Build a 64-bit routing key for fast lookup paths.
inline std::uint64_t makeRoutingKey(std::uint32_t endpointHash, int deviceId)
{
return (static_cast<std::uint64_t>(endpointHash) << 32) | static_cast<std::uint32_t>(deviceId);
}
// Bridge routing key to legacy string-based matching interfaces.
inline QString routingKeyToStableKey(std::uint64_t routingKey)
{
return routingKey == 0 ? QString() : QString::number(routingKey);
}
inline ProtocolType protocolTypeFromHint(const QString& hint)
{
if (hint.compare(QStringLiteral("modbus_rtu"), Qt::CaseInsensitive) == 0) {
return ProtocolType::MODBUS_RTU;
}
if (hint.compare(QStringLiteral("modbus_ascii"), Qt::CaseInsensitive) == 0) {
return ProtocolType::MODBUS_ASCII;
}
if (hint.compare(QStringLiteral("modbus_tcp"), Qt::CaseInsensitive) == 0) {
return ProtocolType::MODBUS_TCP;
}
if (hint.compare(QStringLiteral("can_raw"), Qt::CaseInsensitive) == 0) {
return ProtocolType::CAN_RAW;
}
if (hint.compare(QStringLiteral("can_open"), Qt::CaseInsensitive) == 0) {
return ProtocolType::CAN_OPEN;
}
if (hint.compare(QStringLiteral("udp_custom"), Qt::CaseInsensitive) == 0) {
return ProtocolType::UDP_CUSTOM;
}
return ProtocolType::UNKNOWN;
}
} // namespace softbus::core::models

View File

@@ -1,8 +1,7 @@
#pragma once
#include <cstddef>
#include <cstdint>
#include <QDateTime>
#include <QMetaType>
#include <QString>
@@ -18,18 +17,61 @@ enum class BusDirection
Downstream,
};
enum class ProtocolType : std::uint16_t
{
UNKNOWN = 0,
MODBUS_RTU,
MODBUS_ASCII,
MODBUS_TCP,
CAN_RAW,
CAN_OPEN,
UDP_CUSTOM,
};
inline uint qHash(ProtocolType key, uint seed = 0) noexcept
{
return ::qHash(static_cast<std::uint16_t>(key), seed);
}
union ProtocolHeader
{
struct Can
{
std::uint32_t cobId{0};
bool isExtended{false};
bool isRtr{false};
std::uint8_t padding[2]{0, 0};
} can;
struct Modbus
{
std::uint8_t slaveId{0};
std::uint8_t functionCode{0};
std::uint8_t padding[6]{0, 0, 0, 0, 0, 0};
} modbus;
struct Net
{
std::uint32_t srcIp{0};
std::uint16_t srcPort{0};
std::uint16_t padding{0};
} net;
std::uint64_t alignmentPadding{0};
};
struct RawBusMessage
{
int deviceId{-1};
QString endpoint;
QString stableKey;
QDateTime timestamp{QDateTime::currentDateTimeUtc()};
QString protocolHint;
int deviceId{-1}; // Device instance id, -1 means unbound.
std::uint32_t endpointHash{0}; // Physical endpoint/channel hash.
ProtocolType protocol{ProtocolType::UNKNOWN};
std::uint32_t logicalAddress{0}; // Slave ID / node ID for protocol routing.
std::uint64_t routingKey{0}; // Stable key for MetadataRegistry lookup.
ProtocolHeader header{}; // Out-of-band protocol header metadata.
std::int64_t timestampMs{0}; // UTC unix timestamp in milliseconds.
QString traceId;
softbus::core::models::PayloadRef payload;
std::size_t payloadSize{0};
BusDirection direction{BusDirection::Unknown};
};

View File

@@ -29,9 +29,9 @@ public:
virtual ~IProtocolFramerPlugin() = default;
virtual QString pluginId() const = 0;
virtual bool supports(const QString& protocolHint) const = 0;
virtual softbus::core::models::ProtocolType protocolType() const = 0;
virtual void bindMemoryPool(std::shared_ptr<softbus::core::memory::MemoryPool> pool) = 0;
virtual std::unique_ptr<IProtocolFramerSession> createFramerSession(const QString& endpoint,
virtual std::unique_ptr<IProtocolFramerSession> createFramerSession(std::uint32_t endpointHash,
const QJsonObject& params) = 0;
};

View File

@@ -28,7 +28,7 @@ public:
virtual ~IProtocolMapperPlugin() = default;
virtual QString pluginId() const = 0;
virtual bool supports(const QString& protocolHint) const = 0;
virtual softbus::core::models::ProtocolType protocolType() const = 0;
virtual std::unique_ptr<IProtocolMapperSession> createMapperSession() = 0;
};

View File

@@ -25,7 +25,7 @@ public:
virtual ~IProtocolPlugin() = default;
virtual QString pluginId() const = 0;
virtual bool supports(const QString& protocolHint) const = 0;
virtual softbus::core::models::ProtocolType protocolType() const = 0;
virtual std::unique_ptr<IProtocolSession> createSession() = 0;
};

View File

@@ -8,22 +8,24 @@ void PluginManager::registerProtocolPlugin(std::shared_ptr<IProtocolPlugin> plug
if (!plugin) {
return;
}
m_protocolPlugins.insert(plugin->pluginId(), std::move(plugin));
const auto protocol = plugin->protocolType();
m_protocolPluginsByType.insert(protocol, plugin);
m_protocolPluginsById.insert(plugin->pluginId(), std::move(plugin));
}
std::shared_ptr<IProtocolPlugin> PluginManager::selectProtocolPlugin(const QString& protocolHint) const
std::shared_ptr<IProtocolPlugin> PluginManager::selectProtocolPlugin(softbus::core::models::ProtocolType protocol) const
{
for (auto it = m_protocolPlugins.constBegin(); it != m_protocolPlugins.constEnd(); ++it) {
if (it.value() && it.value()->supports(protocolHint)) {
return it.value();
}
}
return {};
return m_protocolPluginsByType.value(protocol);
}
void PluginManager::unregisterProtocolPlugin(const QString& pluginId)
{
m_protocolPlugins.remove(pluginId);
const auto it = m_protocolPluginsById.find(pluginId);
if (it == m_protocolPluginsById.end() || !it.value()) {
return;
}
m_protocolPluginsByType.remove(it.value()->protocolType());
m_protocolPluginsById.erase(it);
}
void PluginManager::registerProtocolFramerPlugin(std::shared_ptr<IProtocolFramerPlugin> plugin)
@@ -31,22 +33,25 @@ void PluginManager::registerProtocolFramerPlugin(std::shared_ptr<IProtocolFramer
if (!plugin) {
return;
}
m_protocolFramerPlugins.insert(plugin->pluginId(), std::move(plugin));
const auto protocol = plugin->protocolType();
m_protocolFramerPluginsByType.insert(protocol, plugin);
m_protocolFramerPluginsById.insert(plugin->pluginId(), std::move(plugin));
}
std::shared_ptr<IProtocolFramerPlugin> PluginManager::selectProtocolFramerPlugin(const QString& protocolHint) const
std::shared_ptr<IProtocolFramerPlugin> PluginManager::selectProtocolFramerPlugin(
softbus::core::models::ProtocolType protocol) const
{
for (auto it = m_protocolFramerPlugins.constBegin(); it != m_protocolFramerPlugins.constEnd(); ++it) {
if (it.value() && it.value()->supports(protocolHint)) {
return it.value();
}
}
return {};
return m_protocolFramerPluginsByType.value(protocol);
}
void PluginManager::unregisterProtocolFramerPlugin(const QString& pluginId)
{
m_protocolFramerPlugins.remove(pluginId);
const auto it = m_protocolFramerPluginsById.find(pluginId);
if (it == m_protocolFramerPluginsById.end() || !it.value()) {
return;
}
m_protocolFramerPluginsByType.remove(it.value()->protocolType());
m_protocolFramerPluginsById.erase(it);
}
void PluginManager::registerProtocolMapperPlugin(std::shared_ptr<IProtocolMapperPlugin> plugin)
@@ -54,37 +59,40 @@ void PluginManager::registerProtocolMapperPlugin(std::shared_ptr<IProtocolMapper
if (!plugin) {
return;
}
m_protocolMapperPlugins.insert(plugin->pluginId(), std::move(plugin));
const auto protocol = plugin->protocolType();
m_protocolMapperPluginsByType.insert(protocol, plugin);
m_protocolMapperPluginsById.insert(plugin->pluginId(), std::move(plugin));
}
std::shared_ptr<IProtocolMapperPlugin> PluginManager::selectProtocolMapperPlugin(const QString& protocolHint) const
std::shared_ptr<IProtocolMapperPlugin> PluginManager::selectProtocolMapperPlugin(
softbus::core::models::ProtocolType protocol) const
{
for (auto it = m_protocolMapperPlugins.constBegin(); it != m_protocolMapperPlugins.constEnd(); ++it) {
if (it.value() && it.value()->supports(protocolHint)) {
return it.value();
}
}
return {};
return m_protocolMapperPluginsByType.value(protocol);
}
void PluginManager::unregisterProtocolMapperPlugin(const QString& pluginId)
{
m_protocolMapperPlugins.remove(pluginId);
const auto it = m_protocolMapperPluginsById.find(pluginId);
if (it == m_protocolMapperPluginsById.end() || !it.value()) {
return;
}
m_protocolMapperPluginsByType.remove(it.value()->protocolType());
m_protocolMapperPluginsById.erase(it);
}
QStringList PluginManager::registeredProtocolPluginIds() const
{
return m_protocolPlugins.keys();
return m_protocolPluginsById.keys();
}
QStringList PluginManager::registeredProtocolFramerPluginIds() const
{
return m_protocolFramerPlugins.keys();
return m_protocolFramerPluginsById.keys();
}
QStringList PluginManager::registeredProtocolMapperPluginIds() const
{
return m_protocolMapperPlugins.keys();
return m_protocolMapperPluginsById.keys();
}
} // namespace softbus::core::plugin_system

View File

@@ -19,22 +19,27 @@ public:
PluginManager() = default;
void registerProtocolPlugin(std::shared_ptr<IProtocolPlugin> plugin);
std::shared_ptr<IProtocolPlugin> selectProtocolPlugin(const QString& protocolHint) const;
std::shared_ptr<IProtocolPlugin> selectProtocolPlugin(softbus::core::models::ProtocolType protocol) const;
void unregisterProtocolPlugin(const QString& pluginId);
void registerProtocolFramerPlugin(std::shared_ptr<IProtocolFramerPlugin> plugin);
std::shared_ptr<IProtocolFramerPlugin> selectProtocolFramerPlugin(const QString& protocolHint) const;
std::shared_ptr<IProtocolFramerPlugin> selectProtocolFramerPlugin(
softbus::core::models::ProtocolType protocol) const;
void unregisterProtocolFramerPlugin(const QString& pluginId);
void registerProtocolMapperPlugin(std::shared_ptr<IProtocolMapperPlugin> plugin);
std::shared_ptr<IProtocolMapperPlugin> selectProtocolMapperPlugin(const QString& protocolHint) const;
std::shared_ptr<IProtocolMapperPlugin> selectProtocolMapperPlugin(
softbus::core::models::ProtocolType protocol) const;
void unregisterProtocolMapperPlugin(const QString& pluginId);
QStringList registeredProtocolPluginIds() const;
QStringList registeredProtocolFramerPluginIds() const;
QStringList registeredProtocolMapperPluginIds() const;
private:
QHash<QString, std::shared_ptr<IProtocolPlugin>> m_protocolPlugins;
QHash<QString, std::shared_ptr<IProtocolFramerPlugin>> m_protocolFramerPlugins;
QHash<QString, std::shared_ptr<IProtocolMapperPlugin>> m_protocolMapperPlugins;
QHash<QString, std::shared_ptr<IProtocolPlugin>> m_protocolPluginsById;
QHash<softbus::core::models::ProtocolType, std::shared_ptr<IProtocolPlugin>> m_protocolPluginsByType;
QHash<QString, std::shared_ptr<IProtocolFramerPlugin>> m_protocolFramerPluginsById;
QHash<softbus::core::models::ProtocolType, std::shared_ptr<IProtocolFramerPlugin>> m_protocolFramerPluginsByType;
QHash<QString, std::shared_ptr<IProtocolMapperPlugin>> m_protocolMapperPluginsById;
QHash<softbus::core::models::ProtocolType, std::shared_ptr<IProtocolMapperPlugin>> m_protocolMapperPluginsByType;
};
} // namespace softbus::core::plugin_system

View File

@@ -7,6 +7,7 @@
#include <QDateTime>
#include "core/memory/MemoryPool.h"
#include "core/models/MessageRoutingUtils.h"
#include "core/models/RawBusMessage.h"
#include "hardware/drivers/serial/SerialQtDriver.h"
#include "message_bus/ingress/IIngressPort.h"
@@ -115,14 +116,17 @@ void SerialDevice::onRead(const std::vector<std::uint8_t>& data)
// 将数据推送到 ingress 队列 包含端口名、协议、数据、时间戳、traceId
softbus::core::models::RawBusMessage ctx;
ctx.direction = softbus::core::models::BusDirection::Upstream;
ctx.endpoint = m_config.endpoint;
ctx.protocolHint = m_info.protocol;
ctx.endpointHash = softbus::core::models::makeEndpointHash(m_config.endpoint);
ctx.protocol = softbus::core::models::protocolTypeFromHint(m_info.protocol);
ctx.logicalAddress = 0;
ctx.routingKey = softbus::core::models::makeRoutingKey(ctx.endpointHash, m_info.id);
ctx.timestampMs = QDateTime::currentMSecsSinceEpoch();
ctx.deviceId = m_info.id;
ctx.payload.block = std::move(block);
ctx.payload.length = data.size();
ctx.payloadSize = data.size();
ctx.traceId = QStringLiteral("serial:%1:%2")
.arg(m_config.endpoint)
.arg(QDateTime::currentMSecsSinceEpoch());
.arg(ctx.timestampMs);
if (!m_ingress->push(std::move(ctx))) {
m_ingress->reportError(m_config.endpoint, QStringLiteral("ingress queue full"));

View File

@@ -1,5 +1,6 @@
#include "message_bus/egress/EgressRouter.h"
#include "core/models/MessageRoutingUtils.h"
#include "devices/physical/SerialDevice.h"
namespace softbus::message_bus::egress
@@ -19,8 +20,14 @@ void EgressRouter::unbindSerialDevice(const QString& endpoint)
bool EgressRouter::send(const softbus::core::models::RawBusMessage& ctx)
{
auto it = m_serialByEndpoint.constFind(ctx.endpoint);
if (it == m_serialByEndpoint.constEnd() || !it.value() || !ctx.payload.valid()) {
QSharedPointer<softbus::devices::physical::SerialDevice> device;
for (auto it = m_serialByEndpoint.constBegin(); it != m_serialByEndpoint.constEnd(); ++it) {
if (softbus::core::models::makeEndpointHash(it.key()) == ctx.endpointHash) {
device = it.value();
break;
}
}
if (device.isNull() || !ctx.payload.valid()) {
return false;
}
@@ -28,7 +35,7 @@ bool EgressRouter::send(const softbus::core::models::RawBusMessage& ctx)
if (!p) {
return false;
}
return it.value()->writePayload(p, ctx.payload.length);
return device->writePayload(p, ctx.payload.length);
}
} // namespace softbus::message_bus::egress

View File

@@ -45,13 +45,13 @@ bool DynamicRuleRegistry::removeTransformRule(const QString& id)
}
std::vector<FilterRule> DynamicRuleRegistry::snapshotFilterRules(
const QString& endpoint, int deviceId, const QString& stableKey) const
std::uint32_t endpointHash, int deviceId, const QString& stableKey) const
{
std::shared_lock<std::shared_mutex> lk(m_mtx);
std::vector<FilterRule> out;
out.reserve(static_cast<std::size_t>(m_filterRules.size()));
for (auto it = m_filterRules.constBegin(); it != m_filterRules.constEnd(); ++it) {
if (matchScope(it.value().scope, endpoint, deviceId, stableKey)) {
if (matchScope(it.value().scope, endpointHash, deviceId, stableKey)) {
out.push_back(it.value());
}
}
@@ -59,13 +59,13 @@ std::vector<FilterRule> DynamicRuleRegistry::snapshotFilterRules(
}
std::vector<TransformRule> DynamicRuleRegistry::snapshotTransformRules(
const QString& endpoint, int deviceId, const QString& stableKey) const
std::uint32_t endpointHash, int deviceId, const QString& stableKey) const
{
std::shared_lock<std::shared_mutex> lk(m_mtx);
std::vector<TransformRule> out;
out.reserve(static_cast<std::size_t>(m_transformRules.size()));
for (auto it = m_transformRules.constBegin(); it != m_transformRules.constEnd(); ++it) {
if (matchScope(it.value().scope, endpoint, deviceId, stableKey)) {
if (matchScope(it.value().scope, endpointHash, deviceId, stableKey)) {
out.push_back(it.value());
}
}
@@ -82,13 +82,13 @@ QJsonObject DynamicRuleRegistry::status() const
}
bool DynamicRuleRegistry::matchScope(
const RuleScope& scope, const QString& endpoint, int deviceId, const QString& stableKey) const
const RuleScope& scope, std::uint32_t endpointHash, int deviceId, const QString& stableKey) const
{
// hybrid scope: global + endpoint/device/stableKey selective match
const bool endpointOk = scope.endpoint.isEmpty() || scope.endpoint == endpoint;
// scope: global + endpointHash/device/stableKey selective match
const bool endpointHashOk = (scope.endpointHash == 0) || (scope.endpointHash == endpointHash);
const bool deviceOk = scope.deviceId < 0 || scope.deviceId == deviceId;
const bool stableKeyOk = scope.stableKey.isEmpty() || scope.stableKey == stableKey;
return endpointOk && deviceOk && stableKeyOk;
return endpointHashOk && deviceOk && stableKeyOk;
}
} // namespace softbus::message_bus::pipeline

View File

@@ -1,5 +1,6 @@
#pragma once
#include <cstdint>
#include <shared_mutex>
#include <vector>
@@ -12,7 +13,7 @@ namespace softbus::message_bus::pipeline
struct RuleScope
{
QString endpoint;
std::uint32_t endpointHash{0};
int deviceId{-1};
QString stableKey;
};
@@ -43,16 +44,14 @@ public:
bool addTransformRule(const TransformRule& rule);
bool removeTransformRule(const QString& id);
std::vector<FilterRule> snapshotFilterRules(
const QString& endpoint, int deviceId, const QString& stableKey) const;
std::vector<TransformRule> snapshotTransformRules(
const QString& endpoint, int deviceId, const QString& stableKey) const;
std::vector<FilterRule> snapshotFilterRules(std::uint32_t endpointHash, int deviceId, const QString& stableKey) const;
std::vector<TransformRule> snapshotTransformRules(std::uint32_t endpointHash, int deviceId, const QString& stableKey) const;
QJsonObject status() const;
private:
DynamicRuleRegistry() = default;
bool matchScope(const RuleScope& scope, const QString& endpoint, int deviceId, const QString& stableKey) const;
bool matchScope(const RuleScope& scope, std::uint32_t endpointHash, int deviceId, const QString& stableKey) const;
private:
mutable std::shared_mutex m_mtx;

View File

@@ -5,6 +5,7 @@
#include <sstream>
#include <chrono>
#include <functional>
#include "core/models/MessageRoutingUtils.h"
#include "message_bus/pipeline/stages/3_filters/ProtocolParseFilter.h"
#include "utils/logs/logging.h"
@@ -17,10 +18,10 @@ struct EndpointFramingState
std::atomic<bool> running{true};
std::thread th;
std::uint64_t nextSeq{1};
QString endpoint;
std::uint32_t endpointHash{0};
std::shared_ptr<softbus::core::memory::MemoryPool> pool;
std::function<void(softbus::core::models::RawBusMessage&, std::vector<softbus::core::models::RawBusMessage>&)> feed;
std::function<void(QString, std::uint64_t, softbus::core::models::RawBusMessage)> pushFramed;
std::function<void(std::uint32_t, std::uint64_t, softbus::core::models::RawBusMessage)> pushFramed;
explicit EndpointFramingState(std::size_t cap)
: chunkQ(cap)
@@ -46,7 +47,7 @@ void endpointFramerThread(std::shared_ptr<EndpointFramingState> st)
for (auto& x : out) {
const std::uint64_t seq = st->nextSeq++;
if (st->pushFramed) {
st->pushFramed(st->endpoint, seq, std::move(x));
st->pushFramed(st->endpointHash, seq, std::move(x));
}
}
}
@@ -198,15 +199,15 @@ void PipelineEngine::drain()
bool PipelineEngine::enqueueIngress(softbus::core::models::RawBusMessage ctx)
{
if (m_rtConfig.parallelPipeline) {
if (ctx.endpoint.isEmpty()) {
if (ctx.endpointHash == 0) {
++m_counters.drop;
return false;
}
ensureEndpointFramer(ctx.endpoint);
ensureEndpointFramer(ctx.endpointHash);
std::shared_ptr<EndpointFramingState> st;
{
std::lock_guard<std::mutex> lk(m_endpointMutex);
st = m_endpointFramers.value(ctx.endpoint);
st = m_endpointFramers.value(ctx.endpointHash);
}
if (!st || !st->chunkQ.push(std::move(ctx))) {
++m_counters.drop;
@@ -252,25 +253,25 @@ void PipelineEngine::setPluginManager(std::shared_ptr<softbus::core::plugin_syst
// 参数 endpoint 端点
// 返回值 :无
// 逻辑 :如果端点帧解析器不存在 则创建端点帧解析器
void PipelineEngine::ensureEndpointFramer(const QString& endpoint)
void PipelineEngine::ensureEndpointFramer(std::uint32_t endpointHash)
{
std::lock_guard<std::mutex> lk(m_endpointMutex);
if (m_endpointFramers.contains(endpoint)) {
if (m_endpointFramers.contains(endpointHash)) {
return;
}
const std::size_t qcap = m_ingressQ.capacity();
auto st = std::make_shared<EndpointFramingState>(qcap > 0 ? qcap : 4096);
st->endpoint = endpoint;
st->endpointHash = endpointHash;
st->pool = m_pool;
st->feed = [this](softbus::core::models::RawBusMessage& in, std::vector<softbus::core::models::RawBusMessage>& out) {
this->dispatchFramer(in, out);
};
st->pushFramed = [this](QString endpoint, std::uint64_t seq, softbus::core::models::RawBusMessage c) {
st->pushFramed = [this](std::uint32_t endpointHash, std::uint64_t seq, softbus::core::models::RawBusMessage c) {
if (!m_framedQ) {
return;
}
MergeItem item;
item.endpoint = std::move(endpoint);
item.endpointHash = endpointHash;
item.seq = seq;
item.ctx = std::move(c);
item.pipelineOk = true;
@@ -280,7 +281,7 @@ void PipelineEngine::ensureEndpointFramer(const QString& endpoint)
}
};
st->th = std::thread(endpointFramerThread, st);
m_endpointFramers.insert(endpoint, std::move(st));
m_endpointFramers.insert(endpointHash, std::move(st));
}
// 功能 :分发帧解析器
// 参数 chunkIn 数据
@@ -290,14 +291,14 @@ void PipelineEngine::dispatchFramer(
softbus::core::models::RawBusMessage& chunkIn, std::vector<softbus::core::models::RawBusMessage>& completeFramesOut)
{
if (m_pluginManager) {
auto plugin = m_pluginManager->selectProtocolFramerPlugin(chunkIn.protocolHint);
auto plugin = m_pluginManager->selectProtocolFramerPlugin(chunkIn.protocol);
if (plugin) {
plugin->bindMemoryPool(m_pool);
const QString key = chunkIn.endpoint + QStringLiteral("|") + plugin->pluginId();
const SessionKey key{chunkIn.endpointHash, plugin->pluginId()};
std::lock_guard<std::mutex> lk(m_framerSessionMutex);
auto it = m_framerSessions.find(key);
if (it == m_framerSessions.end() || !it.value()) {
auto s = plugin->createFramerSession(chunkIn.endpoint, QJsonObject{});
auto s = plugin->createFramerSession(chunkIn.endpointHash, QJsonObject{});
m_framerSessions.insert(
key, s ? std::shared_ptr<softbus::core::plugin_system::IProtocolFramerSession>(std::move(s)) : nullptr);
it = m_framerSessions.find(key);
@@ -313,10 +314,10 @@ void PipelineEngine::dispatchFramer(
}
}
// 功能 :分配帧序列号
std::uint64_t PipelineEngine::assignFrameSequence(const QString& endpoint)
std::uint64_t PipelineEngine::assignFrameSequence(std::uint32_t endpointHash)
{
std::lock_guard<std::mutex> lk(m_seqMutex);
return ++m_nextFrameSeqByEndpoint[endpoint];
return ++m_nextFrameSeqByEndpoint[endpointHash];
}
void PipelineEngine::runSingleWorker()
@@ -410,11 +411,12 @@ void PipelineEngine::mergerLoop()
void PipelineEngine::ingestMergeItem(MergeItem item)
{
std::lock_guard<std::mutex> lk(m_mergeStateMutex);
auto& st = m_mergeByEndpoint[item.endpoint];
auto& st = m_mergeByEndpoint[item.endpointHash];
if (m_rtConfig.maxReorderDepth > 0
&& static_cast<std::size_t>(st.buffer.size()) >= m_rtConfig.maxReorderDepth) {
++m_counters.mergeDrop;
LOG_WARNING() << "PipelineEngine: merge reorder depth exceeded endpoint=" << item.endpoint;
LOG_WARNING() << "PipelineEngine: merge reorder depth exceeded endpointHash=0x"
<< QString::number(item.endpointHash, 16);
return;
}
st.buffer.insert(item.seq, std::make_pair(std::move(item.ctx), item.pipelineOk));
@@ -477,11 +479,11 @@ std::vector<softbus::core::models::DOMMessage> PipelineEngine::stage2Parser(cons
if (!m_pluginManager) {
return {};
}
auto parserPlugin = m_pluginManager->selectProtocolPlugin(ctx.protocolHint);
auto parserPlugin = m_pluginManager->selectProtocolPlugin(ctx.protocol);
if (!parserPlugin) {
return {};
}
const QString parserKey = ctx.endpoint + QStringLiteral("|") + parserPlugin->pluginId();
const SessionKey parserKey{ctx.endpointHash, parserPlugin->pluginId()};
std::shared_ptr<softbus::core::plugin_system::IProtocolSession> parserSession;
{
std::lock_guard<std::mutex> lk(m_parserSessionMutex);
@@ -503,21 +505,21 @@ std::vector<softbus::core::models::DOMMessage> PipelineEngine::stage2Parser(cons
return {};
}
auto mapperPlugin = m_pluginManager->selectProtocolMapperPlugin(ctx.protocolHint);
auto mapperPlugin = m_pluginManager->selectProtocolMapperPlugin(ctx.protocol);
if (!mapperPlugin) {
return {};
}
const QString key = ctx.endpoint + QStringLiteral("|") + mapperPlugin->pluginId();
const SessionKey mapperKey{ctx.endpointHash, mapperPlugin->pluginId()};
std::shared_ptr<softbus::core::plugin_system::IProtocolMapperSession> session;
{
std::lock_guard<std::mutex> lk(m_mapperSessionMutex);
auto it = m_mapperSessions.find(key);
auto it = m_mapperSessions.find(mapperKey);
if (it == m_mapperSessions.end() || !it.value()) {
auto s = mapperPlugin->createMapperSession();
m_mapperSessions.insert(
key,
mapperKey,
s ? std::shared_ptr<softbus::core::plugin_system::IProtocolMapperSession>(std::move(s)) : nullptr);
it = m_mapperSessions.find(key);
it = m_mapperSessions.find(mapperKey);
}
if (it == m_mapperSessions.end() || !it.value()) {
return {};
@@ -537,7 +539,9 @@ softbus::core::models::EnrichedMessage PipelineEngine::applyTransformAndEnrich(
const softbus::core::models::RawBusMessage& rawCtx, softbus::core::models::DOMMessage& message) const
{
auto rules = softbus::message_bus::pipeline::DynamicRuleRegistry::instance().snapshotTransformRules(
rawCtx.endpoint, rawCtx.deviceId, rawCtx.stableKey);
rawCtx.endpointHash,
rawCtx.deviceId,
softbus::core::models::routingKeyToStableKey(rawCtx.routingKey));
for (const auto& rule : rules) {
const double base = std::visit([](const auto& x) { return static_cast<double>(x); }, message.value);
const double next = base * rule.scale + rule.offset;

View File

@@ -25,6 +25,23 @@
namespace softbus::message_bus::pipeline
{
struct SessionKey
{
std::uint32_t endpointHash{0};
QString pluginId;
bool operator==(const SessionKey& other) const
{
return endpointHash == other.endpointHash && pluginId == other.pluginId;
}
};
inline uint qHash(const SessionKey& key, uint seed = 0) noexcept
{
seed = ::qHash(key.endpointHash, seed);
return ::qHash(key.pluginId, seed);
}
struct PipelineRuntimeConfig
{
bool parallelPipeline{false};
@@ -70,7 +87,7 @@ public:
private:
struct MergeItem
{
QString endpoint;
std::uint32_t endpointHash{0};
std::uint64_t seq{0};
softbus::core::models::RawBusMessage ctx;
bool pipelineOk{false};
@@ -86,11 +103,11 @@ private:
void parseWorkerLoop();
void mergerLoop();
void ensureEndpointFramer(const QString& endpoint);
void ensureEndpointFramer(std::uint32_t endpointHash);
void dispatchFramer(softbus::core::models::RawBusMessage& chunkIn,
std::vector<softbus::core::models::RawBusMessage>& completeFramesOut);
std::uint64_t assignFrameSequence(const QString& endpoint);
std::uint64_t assignFrameSequence(std::uint32_t endpointHash);
bool runStages234(const softbus::core::models::RawBusMessage& ctx);
void ingestMergeItem(MergeItem item);
@@ -113,14 +130,14 @@ private:
std::shared_ptr<softbus::message_bus::pipeline::stages::framers::PassthroughFramer> m_passthroughFramer;
std::mutex m_framerSessionMutex;
QHash<QString, std::shared_ptr<softbus::core::plugin_system::IProtocolFramerSession>> m_framerSessions;
QHash<SessionKey, std::shared_ptr<softbus::core::plugin_system::IProtocolFramerSession>> m_framerSessions;
std::mutex m_parserSessionMutex;
QHash<QString, std::shared_ptr<softbus::core::plugin_system::IProtocolSession>> m_parserSessions;
QHash<SessionKey, std::shared_ptr<softbus::core::plugin_system::IProtocolSession>> m_parserSessions;
std::mutex m_mapperSessionMutex;
QHash<QString, std::shared_ptr<softbus::core::plugin_system::IProtocolMapperSession>> m_mapperSessions;
QHash<SessionKey, std::shared_ptr<softbus::core::plugin_system::IProtocolMapperSession>> m_mapperSessions;
std::mutex m_seqMutex;
QHash<QString, std::uint64_t> m_nextFrameSeqByEndpoint;
QHash<std::uint32_t, std::uint64_t> m_nextFrameSeqByEndpoint;
std::unique_ptr<softbus::core::threading::MutexQueue<MergeItem>> m_framedQ;
std::unique_ptr<softbus::core::threading::MutexQueue<MergeItem>> m_mergeQ;
@@ -128,10 +145,10 @@ private:
std::thread m_mergerThread;
std::mutex m_endpointMutex;
QHash<QString, std::shared_ptr<EndpointFramingState>> m_endpointFramers;
QHash<std::uint32_t, std::shared_ptr<EndpointFramingState>> m_endpointFramers;
std::mutex m_mergeStateMutex;
QHash<QString, MergeState> m_mergeByEndpoint;
QHash<std::uint32_t, MergeState> m_mergeByEndpoint;
int m_count{0}; // 计数器
};

View File

@@ -16,7 +16,7 @@ void PassthroughFramer::feed(softbus::core::models::RawBusMessage& chu
if (!m_pool || !chunkIn.payload.valid()) {
return;
}
const std::size_t n = chunkIn.payloadSize ? chunkIn.payloadSize : chunkIn.payload.length;
const std::size_t n = chunkIn.payload.length;
if (n == 0) {
return;
}
@@ -32,21 +32,21 @@ void PassthroughFramer::feed(softbus::core::models::RawBusMessage& chu
blk->size = n;
softbus::core::models::RawBusMessage out;
out.deviceId = chunkIn.deviceId;
out.stableKey = chunkIn.stableKey;
out.endpoint = chunkIn.endpoint;
out.timestamp = chunkIn.timestamp;
out.protocolHint = chunkIn.protocolHint;
out.traceId = chunkIn.traceId;
out.direction = chunkIn.direction;
out.payloadSize = n;
out.deviceId = chunkIn.deviceId;
out.endpointHash = chunkIn.endpointHash;
out.protocol = chunkIn.protocol;
out.logicalAddress = chunkIn.logicalAddress;
out.routingKey = chunkIn.routingKey;
out.header = chunkIn.header;
out.timestampMs = chunkIn.timestampMs;
out.traceId = chunkIn.traceId;
out.direction = chunkIn.direction;
out.payload.block = std::move(blk);
out.payload.offset = 0;
out.payload.length = n;
completeFramesOut.push_back(std::move(out));
chunkIn.payload = {};
chunkIn.payloadSize = 0;
}
} // namespace softbus::message_bus::pipeline::stages::framers