#include "stdafx.h" #include "ProcessJob.h" #include namespace SERVO { 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; } CProcessJob::CProcessJob(std::string pjId) : m_pjId(trimCopy(pjId)) { clampString(m_pjId, MAX_ID_LEN); } void CProcessJob::setParentCjId(std::string cjId) { m_parentCjId = trimCopy(cjId); clampString(m_parentCjId, MAX_ID_LEN); } void CProcessJob::setRecipe(RecipeMethod method, std::string spec) { m_recipeMethod = method; m_recipeSpec = trimCopy(spec); clampString(m_recipeSpec, MAX_ID_LEN); } void CProcessJob::addParam(std::string name, std::string value) { name = trimCopy(name); value = trimCopy(value); clampString(name, MAX_PARAM_K); clampString(value, MAX_PARAM_V); m_params.push_back({ std::move(name), std::move(value) }); } void CProcessJob::setParams(std::vector params) { m_params.clear(); m_params.reserve(params.size()); for (auto& p : params) addParam(std::move(p.name), std::move(p.value)); } void CProcessJob::addPauseEvent(uint32_t ceid) { if (ceid) m_pauseEvents.push_back(ceid); std::sort(m_pauseEvents.begin(), m_pauseEvents.end()); m_pauseEvents.erase(std::unique(m_pauseEvents.begin(), m_pauseEvents.end()), m_pauseEvents.end()); } void CProcessJob::setPauseEvents(std::vector ceids) { m_pauseEvents = std::move(ceids); std::sort(m_pauseEvents.begin(), m_pauseEvents.end()); m_pauseEvents.erase(std::unique(m_pauseEvents.begin(), m_pauseEvents.end()), m_pauseEvents.end()); } const std::vector& CProcessJob::issue() { return m_issues; } bool CProcessJob::validate(const IResourceView& rv) { m_issues.clear(); // Èà add ͬʱ֧³Ö const char* ºÍ std::string auto add = [&](uint32_t code, std::string msg) { m_issues.push_back({ code, std::move(msg) }); }; if (!rv.isProcessJobsEmpty()) { add(1000, "ProcessJobs Conflict!"); } // ¡ª¡ª »ù±¾ / ±êʶ ¡ª¡ª if (m_pjId.empty()) add(1001, "PJID empty"); if (!asciiPrintable(m_pjId)) add(1002, "PJID has non-printable chars"); // if (m_parentCjId.empty()) add(1010, "Parent CJID empty"); // ¡ª¡ª Åä·½£¨RCPSPEC / PPID£©¡ª¡ª if (m_recipeSpec.empty()) add(1020, "Recipe spec (PPID) empty"); else if (!rv.recipeExists(m_recipeSpec)) { add(1021, "PPID not found: " + m_recipeSpec); } // ¡ª¡ª Åä·½·½·¨ vs ²ÎÊý ¡ª¡ª 1=NoTuning ½ûÖ¹´ø²ÎÊý£»2=WithTuning ÔÊÐí/¿ÉÑ¡ if (m_recipeMethod == RecipeMethod::NoTuning && !m_params.empty()) { add(1022, "Params not allowed when PRRECIPEMETHOD=1 (NoTuning)"); } // ¡ª¡ª ÎïÁÏÑ¡ÔñУÑé ¡ª¡ª£¨¶þѡһ£ºCarrier+Slots »ò MIDs£»Á½Õß¶¼²»ÌîÔò´íÎó£© const bool hasCarrierSlots = !m_carriers.empty(); if (hasCarrierSlots) { // {L:n { CARRIERID {L:j SLOTID} }} for (const auto& cs : m_carriers) { if (cs.carrierId.empty()) { add(1030, "CarrierID empty"); continue; } if (!rv.carrierPresent(cs.carrierId)) { add(1031, "Carrier not present: " + cs.carrierId); } if (cs.slots.empty()) { add(1032, "No slots specified for carrier: " + cs.carrierId); } for (auto s : cs.slots) { if (s == 0) { add(1033, "Slot 0 is invalid for carrier: " + cs.carrierId); continue; } if (!rv.slotUsable(cs.carrierId, s)) { add(1034, "Slot unusable: carrier=" + cs.carrierId + " slot=" + std::to_string(s)); } } } } else { add(1035, "No material selection provided (neither Carrier/Slots nor MIDs)"); } // ¡ª¡ª ÔÝͣʼþ£¨PRPAUSEEVENTID ÁÐ±í£©¡ª¡ª for (auto ceid : m_pauseEvents) { if (!rv.ceidDefined(ceid)) { add(1050, "Pause CEID unknown: " + std::to_string(ceid)); } } return m_issues.empty(); } // ¡ª¡ª ״̬»ú ¡ª¡ª // ¹æÔò¿É°´ÄãÃÇЭÒé΢µ÷ bool CProcessJob::queue() { if (m_state != PJState::NoState) return false; markQueued(); return true; } bool CProcessJob::enterSettingUp() { if (m_state != PJState::Queued) return false; m_state = PJState::SettingUp; return true; } bool CProcessJob::start() { if (m_state != PJState::Queued && m_state != PJState::SettingUp && m_state != PJState::Paused) return false; if (!m_tStart.has_value()) markStart(); m_state = PJState::InProcess; return true; } bool CProcessJob::pause() { if (m_state != PJState::InProcess) return false; m_state = PJState::Paused; return true; } bool CProcessJob::resume() { if (m_state != PJState::Paused) return false; m_state = PJState::InProcess; return true; } bool CProcessJob::complete() { if (m_state != PJState::InProcess && m_state != PJState::Paused) return false; m_state = PJState::Completed; markEnd(); return true; } bool CProcessJob::abort() { if (m_state == PJState::Completed || m_state == PJState::Aborted || m_state == PJState::Failed) return false; m_state = PJState::Aborted; markEnd(); return true; } bool CProcessJob::fail(std::string reason) { m_failReason = trimCopy(reason); clampString(m_failReason, 128); m_state = PJState::Failed; markEnd(); return true; } // ¡ª¡ª ʱ¼ä´Á & ¹¤¾ß ¡ª¡ª void CProcessJob::markQueued() { m_state = PJState::Queued; m_tQueued = std::chrono::system_clock::now(); } void CProcessJob::markStart() { m_tStart = std::chrono::system_clock::now(); } void CProcessJob::markEnd() { m_tEnd = std::chrono::system_clock::now(); } void CProcessJob::clampString(std::string& s, size_t maxLen) { if (s.size() > maxLen) s.resize(maxLen); } bool CProcessJob::asciiPrintable(const std::string& s) { return std::all_of(s.begin(), s.end(), [](unsigned char c) { return c >= 0x20 && c <= 0x7E; }); } void CProcessJob::setCarriers(std::vector carriers) { // ͳһͨ¹ý addCarrier ×ö¹æ·¶»¯£¨È¥¿Õ°×¡¢½Ø¶Ï¡¢È¥ÖØ¡¢ºÏ²¢Í¬ carrier£© m_carriers.clear(); m_carriers.reserve(carriers.size()); for (auto& cs : carriers) { addCarrier(std::move(cs.carrierId), std::move(cs.slots)); } } void CProcessJob::addCarrier(std::string carrierId, std::vector slots) { // 1) ¹æ·¶»¯ carrierId£ºÈ¥¿Õ°× + ³¤¶ÈÏÞÖÆ carrierId = trimCopy(std::move(carrierId)); clampString(carrierId, MAX_ID_LEN); if (carrierId.empty()) { // ¿Õ ID Ö±½ÓºöÂÔ£¨Ò²¿ÉÒÔÑ¡ÔñÅ×Òì³£/¼Ç¼ÈÕÖ¾£¬¿´ÄãÏîÄ¿·ç¸ñ£© return; } // 2) ¹æ·¶»¯ slots£ºÈ¥ 0¡¢ÅÅÐò¡¢È¥ÖØ // ×¢£ºSLOTID °´ 1..N£¬0 ÊÓΪ·Ç·¨/ռλ slots.erase(std::remove(slots.begin(), slots.end(), 0), slots.end()); std::sort(slots.begin(), slots.end()); slots.erase(std::unique(slots.begin(), slots.end()), slots.end()); if (slots.empty()) { // ûÓÐÓÐЧ¿¨Î»¾Í²»×·¼Ó return; } // 3) Èç¹ûÒÑ´æÔÚͬÃûÔØ¾ß£¬ÔòºÏ²¢ slot Áбí auto it = std::find_if(m_carriers.begin(), m_carriers.end(), [&](const CarrierSlotInfo& cs) { return cs.carrierId == carrierId; }); if (it != m_carriers.end()) { // ºÏ²¢ it->slots.insert(it->slots.end(), slots.begin(), slots.end()); std::sort(it->slots.begin(), it->slots.end()); it->slots.erase(std::unique(it->slots.begin(), it->slots.end()), it->slots.end()); } else { // ÐÂÔö CarrierSlotInfo cs; cs.carrierId = std::move(carrierId); cs.slots = std::move(slots); m_carriers.emplace_back(std::move(cs)); } } }