#include "pch.h"
|
#include "ProcessJob.h"
|
#include <cctype>
|
|
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<PJParam> 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<uint32_t> 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());
|
}
|
|
std::vector<CProcessJob::ValidationIssue>
|
CProcessJob::validate(const IResourceView& rv) const
|
{
|
std::vector<ValidationIssue> issues;
|
|
// Èà add ͬʱ֧³Ö const char* ºÍ std::string
|
auto add = [&](uint32_t code, std::string msg) {
|
issues.push_back({ code, std::move(msg) });
|
};
|
|
// ¡ª¡ª »ù±¾ / ±êʶ ¡ª¡ª
|
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 issues;
|
}
|
|
// ¡ª¡ª ״̬»ú ¡ª¡ª
|
// ¹æÔò¿É°´ÄãÃÇÐÒé΢µ÷
|
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<CarrierSlotInfo> 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<uint8_t> 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));
|
}
|
}
|
}
|