#include "stdafx.h" #include "CControlJob.h" #include static inline std::string trimCopy(std::string s) { auto notspace = [](int ch) { return !std::isspace(ch); }; s.erase(s.begin(), std::find_if(s.begin(), s.end(), notspace)); s.erase(std::find_if(s.rbegin(), s.rend(), notspace).base(), s.end()); return s; } namespace SERVO { CControlJob::CControlJob(std::string cjId) : m_cjId(trimCopy(std::move(cjId))) { clampString(m_cjId, MAX_ID_LEN); } CControlJob::CControlJob(CControlJob& src) { m_cjId = src.m_cjId; clampString(m_cjId, MAX_ID_LEN); m_priority = src.m_priority; m_pjIds = src.m_pjIds; m_state = src.m_state; m_failReason = src.m_failReason; m_tQueued = src.m_tQueued; m_tStart = src.m_tStart; m_tEnd = src.m_tEnd; } bool CControlJob::addPJ(const std::string& pjId) { if (pjId.empty()) return false; auto id = pjId; auto it = std::find(m_pjIds.begin(), m_pjIds.end(), id); if (it != m_pjIds.end()) return false; clampString(id, MAX_ID_LEN); m_pjIds.push_back(std::move(id)); return true; } bool CControlJob::addPJs(const std::vector& ids) { bool added = false; for (auto& s : ids) added |= addPJ(s); return added; } bool CControlJob::setPJs(const std::vector& pjs) { m_pjs = pjs; return true; } bool CControlJob::removePJ(const std::string& pjId) { auto it = std::find(m_pjIds.begin(), m_pjIds.end(), pjId); if (it == m_pjIds.end()) return false; m_pjIds.erase(it); return true; } bool CControlJob::containsPJ(const std::string& pjId) const { return std::find(m_pjIds.begin(), m_pjIds.end(), pjId) != m_pjIds.end(); } const std::vector& CControlJob::issues() { return m_issues; } bool CControlJob::validateForCreate( const std::function& canCreateCjFn, const std::function& getPjExistsFn, const std::function& canJoinFn ) { m_issues.clear(); auto add = [&](uint32_t code, std::string msg) { m_issues.push_back({ code, std::move(msg) }); }; // ÊÇ·ñÄÜ´´½¨CJ, ÓÉÉϲã¸ù¾Ýµ±Ç°ÈÎÎñ£¬»úÆ÷״̬µÈ¼ìÑé uint32_t cc; std::string mm; if (!canCreateCjFn(cc, mm)) { add(cc, mm); } // CJID »ù´¡Ð£Ñé if (m_cjId.empty()) add(1101, "CJID empty"); if (!asciiPrintable(m_cjId)) add(1102, "CJID has non-printable chars"); // PJ ÁбíУÑé if (m_pjIds.empty()) add(1110, "PRJOBLIST empty"); for (const auto& pj : m_pjIds) { if (!getPjExistsFn(pj)) add(1111, "PJ not found: " + pj); else if (!canJoinFn(pj)) add(1112, "PJ not joinable: " + pj); } return m_issues.empty(); } // Ó¦Óô´½¨/¸üУ¨ÓÃÓÚ S14F9 ¡ú S14F10 ·¾¶£© CControlJob::CreateResult CControlJob::applyCreate( const CreateRequest& req, const std::function& getPjExistsFn, const std::function& canJoinFn ) { CreateResult r; // ¸²¸ÇÓÅÏȼ¶£¨ÈçÌṩ£© if (req.priority.has_value()) { m_priority = *req.priority; } // Öð PJ Åж¨ for (const auto& pjIdRaw : req.requestedPjIds) { std::string pjId = trimCopy(pjIdRaw); clampString(pjId, MAX_ID_LEN); if (!getPjExistsFn(pjId)) { r.errors.push_back({ 2001, "PRJOBLIST: " + pjId + " not found" }); continue; } if (!canJoinFn(pjId)) { r.errors.push_back({ 2002, "PRJOBLIST: " + pjId + " not joinable (state)" }); continue; } if (containsPJ(pjId)) { // ÒÑÔÚÁÐ±í£¬ÊÓ×÷³É¹¦£¨Ãݵȣ© r.acceptedPjIds.push_back(pjId); continue; } // ¼ÓÈë CJ m_pjIds.push_back(pjId); r.acceptedPjIds.push_back(std::move(pjId)); } // ¹é²¢ ACK if (r.errors.empty()) r.objack = 0; // È«³É¹¦ else if (!r.acceptedPjIds.empty()) r.objack = 1; // ²¿·Ö³É¹¦ else r.objack = 2; // ȫʧ°Ü return r; } // ¡ª¡ª ״̬»ú ¡ª¡ª // bool CControlJob::queue() { if (m_state != CJState::NoState) return false; markQueued(); return true; } bool CControlJob::start() { if (m_state != CJState::Queued) return false; m_state = CJState::Executing; if (!m_tStart.has_value()) markStart(); return true; } bool CControlJob::pause() { if (m_state != CJState::Executing) return false; m_state = CJState::Paused; return true; } bool CControlJob::resume() { if (m_state != CJState::Paused) return false; m_state = CJState::Executing; return true; } bool CControlJob::complete() { if (m_state != CJState::Executing && m_state != CJState::Paused) return false; m_state = CJState::Completed; markEnd(); return true; } bool CControlJob::abort() { if (m_state == CJState::Completed || m_state == CJState::Aborted || m_state == CJState::Failed) return false; m_state = CJState::Aborted; markEnd(); return true; } bool CControlJob::fail(std::string reason) { m_failReason = trimCopy(reason); clampString(m_failReason, 128); m_state = CJState::Failed; markEnd(); return true; } // ¡ª¡ª ¾ÛºÏÍê³ÉÅÐ¶Ï ¡ª¡ª // bool CControlJob::tryAggregateComplete( const std::function& isPjCompletedFn ) { if (m_pjIds.empty()) return false; for (const auto& pj : m_pjIds) { if (!isPjCompletedFn(pj)) return false; } // ËùÓÐ PJ ÒÑÍê³É ¡ú CJ Íê³É return complete(); } // ¡ª¡ª ʱ¼ä´Á ¡ª¡ª // void CControlJob::markQueued() { m_state = CJState::Queued; m_tQueued = std::chrono::system_clock::now(); } void CControlJob::markStart() { m_tStart = std::chrono::system_clock::now(); } void CControlJob::markEnd() { m_tEnd = std::chrono::system_clock::now(); } // ¡ª¡ª ¹¤¾ß ¡ª¡ª // void CControlJob::clampString(std::string& s, size_t maxLen) { if (s.size() > maxLen) s.resize(maxLen); } bool CControlJob::asciiPrintable(const std::string& s) { return std::all_of(s.begin(), s.end(), [](unsigned char c) { return c >= 0x20 && c <= 0x7E; }); } }