mrDarker
2025-08-26 43c7dc211f10851480352b12bd01f3443079bb01
SourceCode/Bond/Servo/ProcessJob.h
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,216 @@
#pragma once
#include <string>
#include <vector>
#include <unordered_map>
#include <unordered_set>
#include <algorithm>
#include <cstdint>
#include <chrono>
#include <optional>
namespace SERVO {
    /// PJ ç”Ÿå‘½å‘¨æœŸï¼ˆè´´è¿‘ E40 å¸¸è§çŠ¶æ€ï¼‰
    enum class PJState : uint8_t {
        NoState = 0,
        Queued,
        SettingUp,
        InProcess,
        Paused,
        Aborting,
        Completed,
        Aborted,
        Failed
    };
    /// é…æ–¹æŒ‡å®šæ–¹å¼ï¼ˆå¯¹åº” S16F15 é‡Œ PRRECIPEMETHOD)
    enum class RecipeMethod : uint8_t {
        NoTuning = 1,   // 1 - recipe without variable tuning
        WithTuning = 2  // 2 - recipe with variable tuning
    };
    /// å¯åŠ¨ç­–ç•¥ï¼ˆå¯¹åº” S16F15 é‡Œ PRPROCESSSTART)
    enum class StartPolicy : uint8_t {
        Queued = 0,   // å»ºç«‹åŽæŽ’队
        AutoStart = 1 // æ¡ä»¶æ»¡è¶³åˆ™è‡ªåŠ¨å¯åŠ¨
    };
    /** é…æ–¹å‚数对(S16F15 ä¸­ RCPPARNM / RCPPARVAL) */
    struct PJParam {
        std::string name;   // RCPPARNM
        std::string value;  // RCPPARVAL
    };
    /**
    {L:2
        CARRIERID
        {L:j
            SLOTID
        }
    }
     */
    struct CarrierSlotInfo {
        std::string carrierId;          // CARRIERID
        std::vector<uint8_t> slots;     // SLOTID[]
        std::vector<void*> contexts;    // Glass
    };
    /// ç®€å•资源视图接口:供 Validate() æŸ¥è¯¢ï¼ˆç”±è®¾å¤‡ç«¯å®žçŽ°è€…åœ¨å¤–éƒ¨æä¾›ï¼‰
    struct IResourceView {
        virtual ~IResourceView() = default;
        virtual bool isProcessJobsEmpty() const = 0;
        virtual bool recipeExists(const std::string& ppid) const = 0;
        virtual bool carrierPresent(const std::string& carrierId) const = 0;
        virtual bool slotUsable(const std::string& carrierId, uint16_t slot) const = 0;
        virtual bool ceidDefined(uint32_t ceid) const = 0;
        // ä½ ä¹Ÿå¯ä»¥æ‰©å±•:port状态、占用情况、CJ/PJ空间等
    };
    /// PJ ä¸»ç±»
    /**
     * ProcessJob â€”— ä¸Ž S16F15(PRJobMultiCreate)字段一一对应的承载类
     *
     * S16F15 ç»“构(核心节选):
     * {L:6
     *   PRJOBID                -> m_pjId
     *   MF                     -> m_mf
     *   {L:n { CARRIERID {L:j SLOTID} } }
     *   {L:3
     *     PRRECIPEMETHOD       -> m_recipeType
     *     RCPSPEC(PPID)      -> m_recipeSpec
     *     {L:m { RCPPARNM RCPPARVAL }}     -> m_params
     *   }
     *   PRPROCESSSTART         -> m_startPolicy
     *   {L:k PRPAUSEEVENTID}   -> m_pauseEvents
     * }
     */
    class CProcessJob {
    public:
        // â€”— æž„造 / åŸºæœ¬è®¾ç½® â€”—
        CProcessJob();
        explicit CProcessJob(std::string pjId);
        const std::string& id() const noexcept { return m_pjId; }
        const std::string& parentCjId() const noexcept { return m_parentCjId; }
        PJState state() const noexcept { return m_state; }
        StartPolicy startPolicy() const noexcept { return m_startPolicy; }
        RecipeMethod recipeMethod() const noexcept { return m_recipeMethod; }
        const std::string& recipeSpec() const noexcept { return m_recipeSpec; } // PPID æˆ– Spec
        std::string getStateText();
        // ç»‘定父 CJ
        void setParentCjId(std::string cjId);
        // é…æ–¹
        void setRecipe(RecipeMethod method, std::string spec);
        // å¯åŠ¨ç­–ç•¥
        void setStartPolicy(StartPolicy sp) { m_startPolicy = sp; }
        // å‚æ•°
        void addParam(std::string name, std::string value);
        void setParams(std::vector<PJParam> params);
        // æš‚停事件
        void addPauseEvent(uint32_t ceid);
        void setPauseEvents(std::vector<uint32_t> ceids);
        // â€”— æ ¡éªŒ â€”—
        struct ValidationIssue {
            uint32_t code;      // è‡ªå®šä¹‰é”™è¯¯ç 
            std::string text;   // æ–‡æœ¬æè¿°
        };
        // è¿”回问题清单(空=通过)
        bool validate(const IResourceView& rv);
        const std::vector<ValidationIssue>& issues();
        // â€”— çŠ¶æ€æœºï¼ˆå¸¦å®ˆå«ï¼‰â€”â€”
        bool queue();           // NoState -> Queued
        bool start();           // Queued/SettingUp -> InProcess
        bool enterSettingUp();  // Queued -> SettingUp
        bool pause();           // InProcess -> Paused
        bool resume();          // Paused -> InProcess
        bool complete();        // InProcess -> Completed
        bool abort();           // Any (未终态) -> Aborted
        bool fail(std::string reason); // ä»»æ„æ€ -> Failed(记录失败原因)
        // â€”— è®¿é—®å™¨ï¼ˆç”¨äºŽä¸ŠæŠ¥/查询)——
        const std::vector<PJParam>& params() const noexcept { return m_params; }
        const std::vector<uint32_t>& pauseEvents() const noexcept { return m_pauseEvents; }
        const std::string& failReason() const noexcept { return m_failReason; }
        // æ—¶é—´æˆ³ï¼ˆå¯ç”¨äºŽæŠ¥è¡¨/追溯)
        std::optional<std::chrono::system_clock::time_point> tQueued() const { return m_tQueued; }
        std::optional<std::chrono::system_clock::time_point> tStart()  const { return m_tStart; }
        std::optional<std::chrono::system_clock::time_point> tEnd()    const { return m_tEnd; }
        // é•¿åº¦é™åˆ¶å·¥å…·ï¼ˆå¯åœ¨é›†æˆæ—¶ç»Ÿä¸€ç­–略)
        static void clampString(std::string& s, size_t maxLen);
        static bool asciiPrintable(const std::string& s);
        // æ¸…空并整体设置
        void setCarriers(std::vector<CarrierSlotInfo> carriers);
        // è¿½åŠ ä¸€ä¸ªè½½å…·
        void addCarrier(std::string carrierId, std::vector<uint8_t> slots);
        // è®¿é—®å™¨
        const std::vector<CarrierSlotInfo>& carriers() const noexcept { return m_carriers; }
        CarrierSlotInfo* getCarrier(std::string& strId);
        // åˆ¤å®šæ˜¯å¦â€œæŒ‰è½½å…·/卡位”方式
        bool usesCarrierSlots() const noexcept { return !m_carriers.empty(); }
    public:
        // ====== ç‰ˆæœ¬å¤´å¸¸é‡ï¼ˆå»ºè®®ä¿ç•™ï¼Œä¾¿äºŽå…¼å®¹ï¼‰======
        static constexpr uint32_t PJ_FILE_MAGIC = 0x504A4A31; // "PJJ1"
        static constexpr uint16_t PJ_FILE_VERSION = 0x0001;
        // ====== æµå¼åºåˆ—化接口 ======
        void serialize(std::ostream& os) const;
        static bool deserialize(std::istream& is, CProcessJob& out, std::string* err = nullptr);
    private:
        // å†…部状态转移帮助
        void markQueued();
        void markStart();
        void markEnd();
    private:
        // æ ‡è¯†
        std::string m_pjId;
        std::string m_parentCjId;
        // é…æ–¹
        RecipeMethod m_recipeMethod{ RecipeMethod::NoTuning };
        std::string  m_recipeSpec; // PPID / Spec
        // ç‰©æ–™
        static constexpr uint8_t MATERIAL_FORMAT = 14; // substrate
        std::vector<CarrierSlotInfo> m_carriers;   // {L:n { CARRIERID {L:j SLOTID} }}
        // å‚æ•° / æš‚停事件
        std::vector<PJParam>    m_params;
        std::vector<uint32_t>   m_pauseEvents;
        // çŠ¶æ€ & è®°å½•
        StartPolicy m_startPolicy{ StartPolicy::Queued }; // 0=Queued, 1=AutoStart
        PJState m_state{ PJState::NoState };
        std::string m_failReason;
        // æ—¶é—´æˆ³
        std::optional<std::chrono::system_clock::time_point> m_tQueued;
        std::optional<std::chrono::system_clock::time_point> m_tStart;
        std::optional<std::chrono::system_clock::time_point> m_tEnd;
        // çº¦æŸï¼ˆå¯æŒ‰ä½ ä»¬åè®®è°ƒæ•´ï¼‰
        static constexpr size_t MAX_ID_LEN = 64;   // PJID/ CJID/ CarrierID/ MID/ PPID
        static constexpr size_t MAX_PARAM_K = 32;   // å‚数名
        static constexpr size_t MAX_PARAM_V = 64;   // å‚数值
        // é”™è¯¯åˆ—表
        std::vector<ValidationIssue> m_issues;
    };
}