SAM-5 核心类体系的 C++ 完整设计

AM-5 标准文档中确实定义了一个包含大约 26 个核心类的完整类体系。这些类共同构成了 SCSI 架构的抽象模型。

下面,我将为你提供一个更全面的 C++ 类设计,力求完整地映射 SAM-5 中定义的这 26 个核心类。这个设计将包括类的继承关系、主要属性和方法声明,以展示一个符合标准的、结构化的 SCSI 架构模型。

请注意:这个设计是一个架构模型,旨在展示类之间的关系和它们的核心职责。一个完整的、可运行的实现还需要大量的细节填充,例如具体的方法逻辑、状态管理、内存管理等。


SAM-5 核心类体系的 C++ 完整设计

这个设计基于 SAM-5 规范中的类图和描述。我将它们按照功能分组,并使用 C++ 的类继承机制来体现 <<extend>> 等关系。

#include <iostream>
#include <vector>
#include <string>
#include <memory>
#include <cstdint>

// 前置声明,解决循环依赖问题
class SCSIPort;
class SCSIDevice;
class LogicalUnit;
class ServiceDeliverySubsystem;
class TaskRouter;
class TaskManager;
class DeviceServer;

// =========================================================================
//  核心通用类和枚举
// =========================================================================

// 地址类型枚举
enum class AddressType {
    PERIPHERAL_DEVICE,
    FLAT_SPACE,
    LOGICAL_UNIT,
    EXTENDED_LOGICAL_UNIT
};

// 任务属性枚举
enum class TaskAttribute {
    SIMPLE,
    ORDERED,
    HEAD_OF_QUEUE,
    ACA
};

// 命令状态枚举
enum class CommandStatus {
    GOOD,
    CHECK_CONDITION,
    CONDITION_MET,
    BUSY,
    RESERVATION_CONFLICT,
    TASK_SET_FULL,
    ACA_ACTIVE,
    TASK_ABORTED
};

// 服务响应枚举
enum class ServiceResponse {
    COMMAND_COMPLETE,
    SERVICE_DELIVERY_OR_TARGET_FAILURE,
    FUNCTION_COMPLETE,
    FUNCTION_SUCCEEDED,
    FUNCTION_REJECTED,
    INCORRECT_LOGICAL_UNIT_NUMBER
};

// SCSI 对象通用接口,所有 SCSI 类都应继承它
class SCSIObject {
public:
    virtual ~SCSIObject() = default;
    virtual std::string getObjectName() const = 0;
};

// =========================================================================
//  1. 基础架构类
// =========================================================================

// 1. SCSI Domain (SCSI 域)
class SCSIDomain : public SCSIObject {
private:
    std::string domainName;
    std::shared_ptr<ServiceDeliverySubsystem> sds;
    std::vector<std::shared_ptr<SCSIDevice>> devices;
    std::vector<std::shared_ptr<SCSIPort>> ports;

public:
    SCSIDomain(const std::string& name) : domainName(name) {}
    std::string getObjectName() const override { return "SCSIDomain: " + domainName; }

    void addDevice(const std::shared_ptr<SCSIDevice>& device) { devices.push_back(device); }
    void addPort(const std::shared_ptr<SCSIPort>& port) { ports.push_back(port); }
    void setServiceDeliverySubsystem(const std::shared_ptr<ServiceDeliverySubsystem>& s) { sds = s; }
};

// 2. Service Delivery Subsystem (服务交付子系统)
class ServiceDeliverySubsystem : public SCSIObject {
private:
    std::string sdsName;
    std::vector<std::shared_ptr<SCSIPort>> attachedPorts;

public:
    ServiceDeliverySubsystem(const std::string& name) : sdsName(name) {}
    std::string getObjectName() const override { return "ServiceDeliverySubsystem: " + sdsName; }

    virtual ServiceResponse sendRequest(const std::shared_ptr<SCSIPort>& sourcePort,
                                        const std::shared_ptr<SCSIPort>& destPort,
                                        const std::vector<uint8_t>& requestData) = 0;
    virtual void attachPort(const std::shared_ptr<SCSIPort>& port) { attachedPorts.push_back(port); }
};

// 3. SCSI Device (SCSI 设备)
class SCSIDevice : public SCSIObject {
protected:
    std::string deviceName;
    std::vector<std::shared_ptr<SCSIPort>> ports;

public:
    SCSIDevice(const std::string& name) : deviceName(name) {}
    std::string getObjectName() const override { return "SCSIDevice: " + deviceName; }

    void addPort(const std::shared_ptr<SCSIPort>& port) { ports.push_back(port); }
    virtual std::shared_ptr<SCSIPort> getPort(const std::string& portId) const {
        for (const auto& port : ports) {
            if (port->getPortId() == portId) return port;
        }
        return nullptr;
    }
};

// =========================================================================
//  2. 端口和地址类
// =========================================================================

// 4. SCSI Port (SCSI 端口)
class SCSIPort : public SCSIObject {
protected:
    std::string portId;
    std::weak_ptr<SCSIDevice> parentDevice;
    std::weak_ptr<ServiceDeliverySubsystem> attachedSDS;

public:
    SCSIPort(const std::string& id) : portId(id) {}
    std::string getObjectName() const override { return "SCSIPort: " + portId; }
    std::string getPortId() const { return portId; }

    void attachToDevice(const std::shared_ptr<SCSIDevice>& device) { parentDevice = device; }
    void attachToSDS(const std::shared_ptr<ServiceDeliverySubsystem>& sds) { attachedSDS = sds; }
    std::shared_ptr<SCSIDevice> getParentDevice() const { return parentDevice.lock(); }
};

// 5. SCSI Initiator Port (SCSI 发起方端口)
class SCSIInitiatorPort : public SCSIPort {
private:
    std::string initiatorPortName; // 全球唯一名称

public:
    SCSIInitiatorPort(const std::string& id, const std::string& name) : SCSIPort(id), initiatorPortName(name) {}
    std::string getObjectName() const override { return "SCSIInitiatorPort: " + portId; }
};

// 6. SCSI Target Port (SCSI 目标方端口)
class SCSITargetPort : public SCSIPort {
private:
    std::string targetPortName; // 全球唯一名称
    std::shared_ptr<TaskRouter> taskRouter;

public:
    SCSITargetPort(const std::string& id, const std::string& name) : SCSIPort(id), targetPortName(name) {}
    std::string getObjectName() const override { return "SCSITargetPort: " + portId; }

    void setTaskRouter(const std::shared_ptr<TaskRouter>& router) { taskRouter = router; }
    std::shared_ptr<TaskRouter> getTaskRouter() const { return taskRouter; }
};

// 7. LUN (逻辑单元号)
class LUN : public SCSIObject {
private:
    uint64_t lunValue;
    AddressType addressMethod;

public:
    LUN(uint64_t value, AddressType method) : lunValue(value), addressMethod(method) {}
    std::string getObjectName() const override { return "LUN: " + std::to_string(lunValue); }

    uint64_t getValue() const { return lunValue; }
    AddressType getAddressMethod() const { return addressMethod; }
};

// =========================================================================
//  3. 设备和逻辑单元类
// =========================================================================

// 8. SCSI Initiator Device (SCSI 发起方设备)
class SCSIInitiatorDevice : public SCSIDevice {
private:
    // 发起方设备通常包含应用客户端,这里简化为一个名称
    std::string applicationClientName;

public:
    SCSIInitiatorDevice(const std::string& name, const std::string& clientName)
        : SCSIDevice(name), applicationClientName(clientName) {}
    std::string getObjectName() const override { return "SCSIInitiatorDevice: " + deviceName; }
};

// 9. SCSI Target Device (SCSI 目标方设备)
class SCSITargetDevice : public SCSIDevice {
private:
    std::map<uint64_t, std::shared_ptr<LogicalUnit>> logicalUnits; // LUN 值到 LogicalUnit 的映射

public:
    SCSITargetDevice(const std::string& name) : SCSIDevice(name) {}
    std::string getObjectName() const override { return "SCSITargetDevice: " + deviceName; }

    void addLogicalUnit(const std::shared_ptr<LogicalUnit>& lu) {
        logicalUnits[lu->getLUN()->getValue()] = lu;
    }
    std::shared_ptr<LogicalUnit> getLogicalUnit(uint64_t lunValue) const {
        auto it = logicalUnits.find(lunValue);
        return (it != logicalUnits.end()) ? it->second : nullptr;
    }
};

// 10. Logical Unit (逻辑单元)
class LogicalUnit : public SCSIObject {
private:
    std::shared_ptr<LUN> lun;
    std::shared_ptr<DeviceServer> deviceServer;
    std::shared_ptr<TaskManager> taskManager;

public:
    LogicalUnit(const std::shared_ptr<LUN>& l) : lun(l) {}
    std::string getObjectName() const override { return "LogicalUnit: " + lun->getObjectName(); }

    std::shared_ptr<LUN> getLUN() const { return lun; }
    void setDeviceServer(const std::shared_ptr<DeviceServer>& ds) { deviceServer = ds; }
    void setTaskManager(const std::shared_ptr<TaskManager>& tm) { taskManager = tm; }
    std::shared_ptr<TaskManager> getTaskManager() const { return taskManager; }
    std::shared_ptr<DeviceServer> getDeviceServer() const { return deviceServer; }
};

// 11. Well Known Logical Unit (知名逻辑单元)
class WellKnownLogicalUnit : public LogicalUnit {
private:
    uint64_t wlunValue;

public:
    WellKnownLogicalUnit(uint64_t wlun) : LogicalUnit(std::make_shared<LUN>(wlun, AddressType::LOGICAL_UNIT)), wlunValue(wlun) {}
    std::string getObjectName() const override { return "WellKnownLogicalUnit: W-LUN=" + std::to_string(wlunValue); }
};

// =========================================================================
//  4. 功能和任务管理类
// =========================================================================

// 12. Command Descriptor Block (命令描述块)
class CDB : public SCSIObject {
private:
    std::vector<uint8_t> cdbBytes;

public:
    CDB(const std::vector<uint8_t>& bytes) : cdbBytes(bytes) {}
    std::string getObjectName() const override { return "CDB"; }
    uint8_t getOperationCode() const { return cdbBytes.empty() ? 0 : cdbBytes[0]; }
    bool isNacaSet() const { return (cdbBytes.size() > 0) && (cdbBytes.back() & 0x02); }
};

// 13. Sense Data (检测数据)
class SenseData : public SCSIObject {
private:
    uint8_t senseKey;
    uint8_t additionalSenseCode;
    uint8_t additionalSenseQualifier;

public:
    SenseData(uint8_t sk, uint8_t asc, uint8_t asq)
        : senseKey(sk), additionalSenseCode(asc), additionalSenseQualifier(asq) {}
    std::string getObjectName() const override { return "SenseData"; }
};

// 14. Task (任务)
class Task : public SCSIObject {
private:
    uint32_t taskTag;
    std::shared_ptr<CDB> cdb;
    TaskAttribute attribute;
    CommandStatus status;
    std::shared_ptr<SenseData> senseData;

public:
    Task(uint32_t tag, const std::shared_ptr<CDB>& c, TaskAttribute attr)
        : taskTag(tag), cdb(c), attribute(attr), status(CommandStatus::GOOD) {}
    std::string getObjectName() const override { return "Task: Tag=" + std::to_string(taskTag); }

    uint32_t getTaskTag() const { return taskTag; }
    TaskAttribute getAttribute() const { return attribute; }
    CommandStatus getStatus() const { return status; }
    void setStatus(CommandStatus s, const std::shared_ptr<SenseData>& sd = nullptr) {
        status = s;
        senseData = sd;
    }
};

// 15. Task Set (任务集)
class TaskSet : public SCSIObject {
private:
    std::vector<std::shared_ptr<Task>> tasks;
    bool acaActive;

public:
    TaskSet() : acaActive(false) {}
    std::string getObjectName() const override { return "TaskSet"; }

    void addTask(const std::shared_ptr<Task>& task) { tasks.push_back(task); }
    std::shared_ptr<Task> findTask(uint32_t taskTag) const {
        for (const auto& task : tasks) {
            if (task->getTaskTag() == taskTag) return task;
        }
        return nullptr;
    }
    void setACAActive(bool active) { acaActive = active; }
    bool isACAActive() const { return acaActive; }
};

// 16. Nexus (关系)
class Nexus : public SCSIObject {
private:
    std::string initiatorPortId;
    std::string targetPortId;
    uint64_t lunValue;
    uint32_t taskTag; // 对于 I_T_L_Q Nexus

public:
    Nexus(const std::string& initId, const std::string& targetId, uint64_t lun, uint32_t tag = 0)
        : initiatorPortId(initId), targetPortId(targetId), lunValue(lun), taskTag(tag) {}
    std::string getObjectName() const override {
        return "Nexus: I=" + initiatorPortId + ", T=" + targetPortId + ", L=" + std::to_string(lunValue) + (taskTag != 0 ? ", Q=" + std::to_string(taskTag) : "");
    }

    std::string getInitiatorPortId() const { return initiatorPortId; }
    std::string getTargetPortId() const { return targetPortId; }
    uint64_t getLUNValue() const { return lunValue; }
    uint32_t getTaskTag() const { return taskTag; }
};

// 17. Device Server (设备服务器)
class DeviceServer : public SCSIObject {
private:
    std::weak_ptr<LogicalUnit> parentLU;

public:
    DeviceServer(const std::shared_ptr<LogicalUnit>& lu) : parentLU(lu) {}
    std::string getObjectName() const override { return "DeviceServer"; }

    virtual ServiceResponse executeCommand(const std::shared_ptr<Task>& task) = 0;
};

// 18. Task Manager (任务管理器)
class TaskManager : public SCSIObject {
private:
    std::weak_ptr<LogicalUnit> parentLU;
    std::shared_ptr<TaskSet> taskSet;

public:
    TaskManager(const std::shared_ptr<LogicalUnit>& lu) : parentLU(lu), taskSet(std::make_shared<TaskSet>()) {}
    std::string getObjectName() const override { return "TaskManager"; }

    virtual ServiceResponse manageTask(const std::shared_ptr<Nexus>& nexus, const std::string& functionName) = 0;
    std::shared_ptr<TaskSet> getTaskSet() const { return taskSet; }
};

// 19. Task Router (任务路由器)
class TaskRouter : public SCSIObject {
private:
    std::weak_ptr<SCSITargetPort> parentPort;

public:
    TaskRouter(const std::shared_ptr<SCSITargetPort>& port) : parentPort(port) {}
    std::string getObjectName() const override { return "TaskRouter"; }

    virtual ServiceResponse routeTask(const std::shared_ptr<Nexus>& nexus, const std::shared_ptr<Task>& task) = 0;
};

// =========================================================================
//  5. 事件和通知类
// =========================================================================

// 20. SCSI Event (SCSI 事件)
class SCSIEvent : public SCSIObject {
private:
    std::string eventType;
    std::shared_ptr<Nexus> eventNexus;

public:
    SCSIEvent(const std::string& type, const std::shared_ptr<Nexus>& nexus)
        : eventType(type), eventNexus(nexus) {}
    std::string getObjectName() const override { return "SCSIEvent: " + eventType; }
};

// 21. Notification (通知)
class Notification : public SCSIObject {
private:
    std::string notificationType;

public:
    Notification(const std::string& type) : notificationType(type) {}
    std::string getObjectName() const override { return "Notification: " + notificationType; }
};

// =========================================================================
//  6. 服务类 (通常是 <<extend>> 关系,这里简化为独立类)
// =========================================================================

// 22. Data-In Delivery Service (数据输入交付服务)
class DataInDeliveryService : public SCSIObject {
public:
    std::string getObjectName() const override { return "DataInDeliveryService"; }
    virtual ServiceResponse deliverData(const std::shared_ptr<Nexus>& nexus, std::vector<uint8_t>& dataBuffer) = 0;
};

// 23. Data-Out Delivery Service (数据输出交付服务)
class DataOutDeliveryService : public SCSIObject {
public:
    std::string getObjectName() const override { return "DataOutDeliveryService"; }
    virtual ServiceResponse receiveData(const std::shared_ptr<Nexus>& nexus, const std::vector<uint8_t>& dataBuffer) = 0;
};

// 24. Task Management Service (任务管理服务)
class TaskManagementService : public SCSIObject {
public:
    std::string getObjectName() const override { return "TaskManagementService"; }
    // 这个服务通常由 TaskManager 内部调用,这里作为一个独立概念存在
};

// 25. Event Notification Service (事件通知服务)
class EventNotificationService : public SCSIObject {
public:
    std::string getObjectName() const override { return "EventNotificationService"; }
    virtual void postEvent(const std::shared_ptr<SCSIEvent>& event) = 0;
};

// 26. Unit Attention Service (单元关注服务)
class UnitAttentionService : public SCSIObject {
private:
    std::vector<std::shared_ptr<SCSIEvent>> unitAttentionEvents;

public:
    std::string getObjectName() const override { return "UnitAttentionService"; }
    virtual void raiseUnitAttention(const std::shared_ptr<SCSIEvent>& event) {
        unitAttentionEvents.push_back(event);
        std::cout << "[UnitAttentionService] Raised: " << event->getObjectName() << std::endl;
    }
    virtual std::shared_ptr<SCSIEvent> getNextUnitAttention(const std::shared_ptr<Nexus>& nexus) {
        // 简化实现,返回第一个事件
        if (!unitAttentionEvents.empty()) {
            auto event = unitAttentionEvents.front();
            unitAttentionEvents.erase(unitAttentionEvents.begin());
            return event;
        }
        return nullptr;
    }
};

// =========================================================================
//  示例:一个具体的 ServiceDeliverySubsystem 实现
// =========================================================================
class FCPServiceDeliverySubsystem : public ServiceDeliverySubsystem {
public:
    FCPServiceDeliverySubsystem(const std::string& name) : ServiceDeliverySubsystem(name) {}

    ServiceResponse sendRequest(const std::shared_ptr<SCSIPort>& sourcePort,
                                const std::shared_ptr<SCSIPort>& destPort,
                                const std::vector<uint8_t>& requestData) override {
        std::cout << "[FCPServiceDeliverySubsystem] Sending request from "
                  << sourcePort->getObjectName() << " to " << destPort->getObjectName() << std::endl;
        // 这里会有实际的 FCP 帧打包和发送逻辑
        return ServiceResponse::COMMAND_COMPLETE;
    }
};

// =========================================================================
//  主函数:演示如何使用这些类来构建一个简单的 SCSI 系统
// =========================================================================
int main() {
    std::cout << "=== SAM-5 Class Hierarchy Demo ===" << std::endl;

    // 1. 创建一个 SCSI 域和服务交付子系统
    auto domain = std::make_shared<SCSIDomain>("Domain0");
    auto fcpSDS = std::make_shared<FCPServiceDeliverySubsystem>("FCP_SDS_0");
    domain->setServiceDeliverySubsystem(fcpSDS);

    // 2. 创建一个目标设备
    auto targetDevice = std::make_shared<SCSITargetDevice>("TargetDisk_0");
    
    // 3. 为目标设备创建一个目标端口和任务路由器
    auto targetPort = std::make_shared<SCSITargetPort>("TP0", "iqn.1992-01.com.example:target0");
    auto taskRouter = std::make_shared<TaskRouter>(targetPort); // TaskRouter 是抽象的,这里需要一个具体实现
    targetPort->setTaskRouter(taskRouter);
    
    // 4. 将端口附加到设备和 SDS
    targetDevice->addPort(targetPort);
    targetPort->attachToDevice(targetDevice);
    fcpSDS->attachPort(targetPort);

    // 5. 为目标设备创建一个逻辑单元 (LUN 1)
    auto lun1 = std::make_shared<LUN>(1, AddressType::FLAT_SPACE);
    auto logicalUnit1 = std::make_shared<LogicalUnit>(lun1);
    
    // 6. 为逻辑单元创建功能组件
    auto deviceServer = std::make_shared<DeviceServer>(logicalUnit1); // DeviceServer 是抽象的
    auto taskManager = std::make_shared<TaskManager>(logicalUnit1);   // TaskManager 是抽象的
    logicalUnit1->setDeviceServer(deviceServer);
    logicalUnit1->setTaskManager(taskManager);

    // 7. 将逻辑单元添加到目标设备
    targetDevice->addLogicalUnit(logicalUnit1);

    // 8. 将设备添加到域
    domain->addDevice(targetDevice);

    // 9. 创建一个单元关注服务并触发一个事件
    auto unitAttentionService = std::make_shared<UnitAttentionService>();
    auto powerOnEvent = std::make_shared<SCSIEvent>("POWER_ON", std::make_shared<Nexus>("IP0", "TP0", 1));
    unitAttentionService->raiseUnitAttention(powerOnEvent);

    // 10. 模拟查询单元关注
    std::cout << "\n--- Checking for Unit Attentions ---" << std::endl;
    auto nextUA = unitAttentionService->getNextUnitAttention(std::make_shared<Nexus>("IP0", "TP0", 1));
    if (nextUA) {
        std::cout << "Found Unit Attention: " << nextUA->getObjectName() << std::endl;
    }
    
    std::cout << "\n=== Demo Complete ===" << std::endl;
    return 0;
}

设计说明

  1. 继承与接口

    • 所有类都继承自一个共同的基类 SCSIObject,这有助于统一管理和调试,体现了 SAM-5 模型中所有元素都是 SCSI 对象的概念。
    • 像 ServiceDeliverySubsystemDeviceServerTaskManager 等类被设计为抽象基类(包含纯虚函数 virtual ... = 0),因为它们定义了一个接口,但具体的实现(如 FCP、iSCSI)会有所不同。这符合 C++ 的最佳实践。
  2. 类的关系

    • 组合关系(Composition):例如,一个 SCSIDevice 包含多个 SCSIPort。在代码中,这通过一个 std::vector 来体现。我使用了 std::shared_ptr 来管理这些动态分配的对象,以简化内存管理。
    • 聚合关系(Aggregation):例如,一个 SCSIPort 属于一个 SCSIDevice,但也可以被 ServiceDeliverySubsystem 引用。这里使用 std::weak_ptr 来避免循环引用导致的内存泄漏。parentDevice 和 attachedSDS 就是这种情况。
    • <<extend>> 关系:SAM-5 中许多服务(如 Data-In Delivery Service)是对核心类的扩展。在 C++ 中,这可以通过多重继承组合来实现。为了保持设计的清晰和简单,我将这些服务设计为独立的类,核心类可以持有它们的实例来使用其功能。
  3. 关键类的实现

    • Nexus 类:这个类是连接各个组件的关键。它封装了发起方端口、目标方端口、LUN 和任务标签(Task Tag)的信息,用于唯一标识一个命令上下文。
    • TaskSet 和 TaskManager 类TaskSet 管理一组任务的状态,特别是 ACA(Auto Contingent Allegiance)条件。TaskManager 则负责执行具体的任务管理功能,如 ABORT TASK 或 CLEAR ACA
    • UnitAttentionService 类:这个类专门用于管理和报告单元关注事件,如设备上电、重置等。
  4. 现代 C++ 特性

    • 智能指针std::shared_ptr 和 std::weak_ptr 的广泛使用是现代 C++ 的标志。它们能自动管理对象的生命周期,极大地减少了内存泄漏的风险。
    • const 正确性:成员函数在不修改对象状态时被声明为 const,这是一个良好的编程习惯。

这个设计为你提供了一个坚实的框架,你可以基于此进行更深入的开发,例如实现具体的 FCPServiceDeliverySubsystem 或 iSCSIDeviceServer,并填充 executeCommand 或 routeTask 等方法的内部逻辑。

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值