void PrePostProcessor::CheckPostQueue() { GuardedDownloadQueue downloadQueue = DownloadQueue::Guard(); size_t countBefore = m_activeJobs.size(); CheckRequestPar(downloadQueue); CleanupJobs(downloadQueue); bool changed = m_activeJobs.size() != countBefore; bool allowPar; while (CanRunMoreJobs(&allowPar) && !IsStopped()) { NzbInfo* postJob = PickNextJob(downloadQueue, allowPar); if (!postJob) { break; } m_activeJobs.push_back(postJob); PostInfo* postInfo = postJob->GetPostInfo(); if (postInfo->GetStage() == PostInfo::ptQueued && (!g_Options->GetPausePostProcess() || postInfo->GetNzbInfo()->GetForcePriority())) { StartJob(downloadQueue, postInfo, allowPar); CheckRequestPar(downloadQueue); CleanupJobs(downloadQueue); changed = true; } } if (changed) { downloadQueue->Save(); UpdatePauseState(); } Util::SetStandByMode(m_activeJobs.empty()); }
void PrePostProcessor::StartJob(DownloadQueue* pDownloadQueue, PostInfo* pPostInfo) { #ifndef DISABLE_PARCHECK if (pPostInfo->GetNZBInfo()->GetRenameStatus() == NZBInfo::rsNone) { UpdatePauseState(g_pOptions->GetParPauseQueue(), "par-rename"); m_ParCoordinator.StartParRenameJob(pPostInfo); return; } else if (pPostInfo->GetNZBInfo()->GetParStatus() == NZBInfo::psNone) { if (m_ParCoordinator.FindMainPars(pPostInfo->GetNZBInfo()->GetDestDir(), NULL)) { UpdatePauseState(g_pOptions->GetParPauseQueue(), "par-check"); m_ParCoordinator.StartParCheckJob(pPostInfo); } else { info("Nothing to par-check for %s", pPostInfo->GetInfoName()); pPostInfo->GetNZBInfo()->SetParStatus(NZBInfo::psSkipped); pPostInfo->SetWorking(false); pPostInfo->SetStage(PostInfo::ptQueued); } return; } #endif NZBParameter* pUnpackParameter = pPostInfo->GetNZBInfo()->GetParameters()->Find("*Unpack:", false); bool bUnpackParam = !(pUnpackParameter && !strcasecmp(pUnpackParameter->GetValue(), "no")); bool bUnpack = bUnpackParam && (pPostInfo->GetNZBInfo()->GetUnpackStatus() == NZBInfo::usNone); bool bParFailed = pPostInfo->GetNZBInfo()->GetParStatus() == NZBInfo::psFailure || pPostInfo->GetNZBInfo()->GetParStatus() == NZBInfo::psRepairPossible || pPostInfo->GetNZBInfo()->GetParStatus() == NZBInfo::psManual; bool bCleanup = !bUnpack && pPostInfo->GetNZBInfo()->GetCleanupStatus() == NZBInfo::csNone && (pPostInfo->GetNZBInfo()->GetParStatus() == NZBInfo::psSuccess || (pPostInfo->GetNZBInfo()->GetUnpackStatus() == NZBInfo::usSuccess && pPostInfo->GetNZBInfo()->GetParStatus() != NZBInfo::psFailure)) && strlen(g_pOptions->GetExtCleanupDisk()) > 0; bool bMoveInter = !bUnpack && pPostInfo->GetNZBInfo()->GetMoveStatus() == NZBInfo::msNone && pPostInfo->GetNZBInfo()->GetUnpackStatus() != NZBInfo::usFailure && pPostInfo->GetNZBInfo()->GetParStatus() != NZBInfo::psFailure && pPostInfo->GetNZBInfo()->GetParStatus() != NZBInfo::psManual && strlen(g_pOptions->GetInterDir()) > 0 && !strncmp(pPostInfo->GetNZBInfo()->GetDestDir(), g_pOptions->GetInterDir(), strlen(g_pOptions->GetInterDir())); // TODO: check if download has pp-scripts defined bool bPostScript = true; if (bUnpack && bParFailed) { warn("Skipping unpack due to %s for %s", pPostInfo->GetNZBInfo()->GetParStatus() == NZBInfo::psManual ? "required par-repair" : "par-failure", pPostInfo->GetInfoName()); pPostInfo->GetNZBInfo()->SetUnpackStatus(NZBInfo::usSkipped); bUnpack = false; } if (!bUnpack && !bMoveInter && !bPostScript) { pPostInfo->SetStage(PostInfo::ptFinished); return; } pPostInfo->SetProgressLabel(bUnpack ? "Unpacking" : bMoveInter ? "Moving" : "Executing post-process-script"); pPostInfo->SetWorking(true); pPostInfo->SetStage(bUnpack ? PostInfo::ptUnpacking : bMoveInter ? PostInfo::ptMoving : PostInfo::ptExecutingScript); pPostInfo->SetFileProgress(0); pPostInfo->SetStageProgress(0); SaveQueue(pDownloadQueue); if (!pPostInfo->GetStartTime()) { pPostInfo->SetStartTime(time(NULL)); } pPostInfo->SetStageTime(time(NULL)); if (bUnpack) { UpdatePauseState(g_pOptions->GetUnpackPauseQueue(), "unpack"); UnpackController::StartJob(pPostInfo); } else if (bCleanup) { UpdatePauseState(g_pOptions->GetUnpackPauseQueue() || g_pOptions->GetScriptPauseQueue(), "cleanup"); CleanupController::StartJob(pPostInfo); } else if (bMoveInter) { UpdatePauseState(g_pOptions->GetUnpackPauseQueue() || g_pOptions->GetScriptPauseQueue(), "move"); MoveController::StartJob(pPostInfo); } else { UpdatePauseState(g_pOptions->GetScriptPauseQueue(), "post-process-script"); PostScriptController::StartJob(pPostInfo); } }
void PrePostProcessor::CheckPostQueue() { DownloadQueue* pDownloadQueue = g_pQueueCoordinator->LockQueue(); if (!pDownloadQueue->GetPostQueue()->empty()) { PostInfo* pPostInfo = pDownloadQueue->GetPostQueue()->front(); if (!pPostInfo->GetWorking()) { #ifndef DISABLE_PARCHECK if (pPostInfo->GetRequestParCheck() && pPostInfo->GetNZBInfo()->GetParStatus() <= NZBInfo::psSkipped && g_pOptions->GetParCheck() != Options::pcManual) { pPostInfo->GetNZBInfo()->SetParStatus(NZBInfo::psNone); pPostInfo->SetRequestParCheck(false); pPostInfo->SetStage(PostInfo::ptQueued); pPostInfo->GetNZBInfo()->GetScriptStatuses()->Clear(); DeletePostThread(pPostInfo); } else if (pPostInfo->GetRequestParCheck() && pPostInfo->GetNZBInfo()->GetParStatus() <= NZBInfo::psSkipped && g_pOptions->GetParCheck() == Options::pcManual) { pPostInfo->SetRequestParCheck(false); pPostInfo->GetNZBInfo()->SetParStatus(NZBInfo::psManual); DeletePostThread(pPostInfo); FileInfo* pFileInfo = GetQueueGroup(pDownloadQueue, pPostInfo->GetNZBInfo()); if (pFileInfo) { info("Downloading all remaining files for manual par-check for %s", pPostInfo->GetNZBInfo()->GetName()); g_pQueueCoordinator->GetQueueEditor()->LockedEditEntry(pDownloadQueue, pFileInfo->GetID(), false, QueueEditor::eaGroupResume, 0, NULL); pPostInfo->SetStage(PostInfo::ptFinished); pPostInfo->GetNZBInfo()->SetPostProcess(false); } else { info("There are no par-files remain for download for %s", pPostInfo->GetNZBInfo()->GetName()); pPostInfo->SetStage(PostInfo::ptQueued); } } else if (pPostInfo->GetRequestParRename()) { pPostInfo->GetNZBInfo()->SetRenameStatus(NZBInfo::rsNone); pPostInfo->SetRequestParRename(false); pPostInfo->SetStage(PostInfo::ptQueued); DeletePostThread(pPostInfo); } #endif if (pPostInfo->GetDeleted()) { pPostInfo->SetStage(PostInfo::ptFinished); } if (pPostInfo->GetStage() == PostInfo::ptQueued && !g_pOptions->GetPausePostProcess()) { DeletePostThread(pPostInfo); StartJob(pDownloadQueue, pPostInfo); } else if (pPostInfo->GetStage() == PostInfo::ptFinished) { UpdatePauseState(false, NULL); JobCompleted(pDownloadQueue, pPostInfo); } else if (!g_pOptions->GetPausePostProcess()) { error("Internal error: invalid state in post-processor"); } } } g_pQueueCoordinator->UnlockQueue(); }
void PrePostProcessor::StartJob(DownloadQueue* downloadQueue, PostInfo* postInfo) { if (!postInfo->GetStartTime()) { postInfo->SetStartTime(Util::CurrentTime()); } #ifndef DISABLE_PARCHECK if (postInfo->GetNzbInfo()->GetRenameStatus() == NzbInfo::rsNone && postInfo->GetNzbInfo()->GetDeleteStatus() == NzbInfo::dsNone) { UpdatePauseState(g_Options->GetParPauseQueue(), "par-rename"); m_parCoordinator.StartParRenameJob(postInfo); return; } else if (postInfo->GetNzbInfo()->GetParStatus() == NzbInfo::psNone && postInfo->GetNzbInfo()->GetDeleteStatus() == NzbInfo::dsNone) { if (ParParser::FindMainPars(postInfo->GetNzbInfo()->GetDestDir(), nullptr)) { UpdatePauseState(g_Options->GetParPauseQueue(), "par-check"); m_parCoordinator.StartParCheckJob(postInfo); } else { postInfo->GetNzbInfo()->PrintMessage(Message::mkInfo, "Nothing to par-check for %s", postInfo->GetNzbInfo()->GetName()); postInfo->GetNzbInfo()->SetParStatus(NzbInfo::psSkipped); postInfo->SetWorking(false); postInfo->SetStage(PostInfo::ptQueued); } return; } else if (postInfo->GetNzbInfo()->GetParStatus() == NzbInfo::psSkipped && ((g_Options->GetParScan() != Options::psDupe && postInfo->GetNzbInfo()->CalcHealth() < postInfo->GetNzbInfo()->CalcCriticalHealth(false) && postInfo->GetNzbInfo()->CalcCriticalHealth(false) < 1000) || postInfo->GetNzbInfo()->CalcHealth() == 0) && ParParser::FindMainPars(postInfo->GetNzbInfo()->GetDestDir(), nullptr)) { if (postInfo->GetNzbInfo()->CalcHealth() == 0) { postInfo->GetNzbInfo()->PrintMessage(Message::mkWarning, "Skipping par-check for %s due to health 0%%", postInfo->GetNzbInfo()->GetName()); } else { postInfo->GetNzbInfo()->PrintMessage(Message::mkWarning, "Skipping par-check for %s due to health %.1f%% below critical %.1f%%", postInfo->GetNzbInfo()->GetName(), postInfo->GetNzbInfo()->CalcHealth() / 10.0, postInfo->GetNzbInfo()->CalcCriticalHealth(false) / 10.0); } postInfo->GetNzbInfo()->SetParStatus(NzbInfo::psFailure); return; } else if (postInfo->GetNzbInfo()->GetParStatus() == NzbInfo::psSkipped && postInfo->GetNzbInfo()->GetFailedSize() - postInfo->GetNzbInfo()->GetParFailedSize() > 0 && ParParser::FindMainPars(postInfo->GetNzbInfo()->GetDestDir(), nullptr)) { postInfo->GetNzbInfo()->PrintMessage(Message::mkInfo, "Collection %s with health %.1f%% needs par-check", postInfo->GetNzbInfo()->GetName(), postInfo->GetNzbInfo()->CalcHealth() / 10.0); postInfo->SetRequestParCheck(true); return; } #endif NzbParameter* unpackParameter = postInfo->GetNzbInfo()->GetParameters()->Find("*Unpack:", false); bool unpackParam = !(unpackParameter && !strcasecmp(unpackParameter->GetValue(), "no")); bool unpack = unpackParam && postInfo->GetNzbInfo()->GetUnpackStatus() == NzbInfo::usNone && postInfo->GetNzbInfo()->GetDeleteStatus() == NzbInfo::dsNone; bool parFailed = postInfo->GetNzbInfo()->GetParStatus() == NzbInfo::psFailure || postInfo->GetNzbInfo()->GetParStatus() == NzbInfo::psRepairPossible || postInfo->GetNzbInfo()->GetParStatus() == NzbInfo::psManual; bool cleanup = !unpack && postInfo->GetNzbInfo()->GetCleanupStatus() == NzbInfo::csNone && !Util::EmptyStr(g_Options->GetExtCleanupDisk()) && ((postInfo->GetNzbInfo()->GetParStatus() == NzbInfo::psSuccess && postInfo->GetNzbInfo()->GetUnpackStatus() != NzbInfo::usFailure && postInfo->GetNzbInfo()->GetUnpackStatus() != NzbInfo::usSpace && postInfo->GetNzbInfo()->GetUnpackStatus() != NzbInfo::usPassword) || (postInfo->GetNzbInfo()->GetUnpackStatus() == NzbInfo::usSuccess && postInfo->GetNzbInfo()->GetParStatus() != NzbInfo::psFailure) || ((postInfo->GetNzbInfo()->GetUnpackStatus() == NzbInfo::usNone || postInfo->GetNzbInfo()->GetUnpackStatus() == NzbInfo::usSkipped) && (postInfo->GetNzbInfo()->GetParStatus() == NzbInfo::psNone || postInfo->GetNzbInfo()->GetParStatus() == NzbInfo::psSkipped) && postInfo->GetNzbInfo()->CalcHealth() == 1000)); bool moveInter = !unpack && postInfo->GetNzbInfo()->GetMoveStatus() == NzbInfo::msNone && postInfo->GetNzbInfo()->GetUnpackStatus() != NzbInfo::usFailure && postInfo->GetNzbInfo()->GetUnpackStatus() != NzbInfo::usSpace && postInfo->GetNzbInfo()->GetUnpackStatus() != NzbInfo::usPassword && postInfo->GetNzbInfo()->GetParStatus() != NzbInfo::psFailure && postInfo->GetNzbInfo()->GetParStatus() != NzbInfo::psManual && postInfo->GetNzbInfo()->GetDeleteStatus() == NzbInfo::dsNone && !Util::EmptyStr(g_Options->GetInterDir()) && !strncmp(postInfo->GetNzbInfo()->GetDestDir(), g_Options->GetInterDir(), strlen(g_Options->GetInterDir())) && postInfo->GetNzbInfo()->GetDestDir()[strlen(g_Options->GetInterDir())] == PATH_SEPARATOR; bool postScript = true; if (unpack && parFailed) { postInfo->GetNzbInfo()->PrintMessage(Message::mkWarning, "Skipping unpack for %s due to %s", postInfo->GetNzbInfo()->GetName(), postInfo->GetNzbInfo()->GetParStatus() == NzbInfo::psManual ? "required par-repair" : "par-failure"); postInfo->GetNzbInfo()->SetUnpackStatus(NzbInfo::usSkipped); unpack = false; } if (!unpack && !moveInter && !postScript) { postInfo->SetStage(PostInfo::ptFinished); return; } postInfo->SetProgressLabel(unpack ? "Unpacking" : moveInter ? "Moving" : "Executing post-process-script"); postInfo->SetWorking(true); postInfo->SetStage(unpack ? PostInfo::ptUnpacking : moveInter ? PostInfo::ptMoving : PostInfo::ptExecutingScript); postInfo->SetFileProgress(0); postInfo->SetStageProgress(0); downloadQueue->Save(); postInfo->SetStageTime(Util::CurrentTime()); if (unpack) { UpdatePauseState(g_Options->GetUnpackPauseQueue(), "unpack"); UnpackController::StartJob(postInfo); } else if (cleanup) { UpdatePauseState(g_Options->GetUnpackPauseQueue() || g_Options->GetScriptPauseQueue(), "cleanup"); CleanupController::StartJob(postInfo); } else if (moveInter) { UpdatePauseState(g_Options->GetUnpackPauseQueue() || g_Options->GetScriptPauseQueue(), "move"); MoveController::StartJob(postInfo); } else { UpdatePauseState(g_Options->GetScriptPauseQueue(), "post-process-script"); PostScriptController::StartJob(postInfo); } }
void PrePostProcessor::CheckPostQueue() { GuardedDownloadQueue downloadQueue = DownloadQueue::Guard(); if (!m_curJob && m_jobCount > 0) { m_curJob = GetNextJob(downloadQueue); } if (m_curJob) { PostInfo* postInfo = m_curJob->GetPostInfo(); if (!postInfo->GetWorking() && !IsNzbFileDownloading(m_curJob)) { #ifndef DISABLE_PARCHECK if (postInfo->GetRequestParCheck() && (postInfo->GetNzbInfo()->GetParStatus() <= NzbInfo::psSkipped || (postInfo->GetForceRepair() && !postInfo->GetNzbInfo()->GetParFull())) && g_Options->GetParCheck() != Options::pcManual) { postInfo->SetForceParFull(postInfo->GetNzbInfo()->GetParStatus() > NzbInfo::psSkipped); postInfo->GetNzbInfo()->SetParStatus(NzbInfo::psNone); postInfo->SetRequestParCheck(false); postInfo->SetStage(PostInfo::ptQueued); postInfo->GetNzbInfo()->GetScriptStatuses()->clear(); DeletePostThread(postInfo); } else if (postInfo->GetRequestParCheck() && postInfo->GetNzbInfo()->GetParStatus() <= NzbInfo::psSkipped && g_Options->GetParCheck() == Options::pcManual) { postInfo->SetRequestParCheck(false); postInfo->GetNzbInfo()->SetParStatus(NzbInfo::psManual); DeletePostThread(postInfo); if (!postInfo->GetNzbInfo()->GetFileList()->empty()) { postInfo->GetNzbInfo()->PrintMessage(Message::mkInfo, "Downloading all remaining files for manual par-check for %s", postInfo->GetNzbInfo()->GetName()); downloadQueue->EditEntry(postInfo->GetNzbInfo()->GetId(), DownloadQueue::eaGroupResume, 0, nullptr); postInfo->SetStage(PostInfo::ptFinished); } else { postInfo->GetNzbInfo()->PrintMessage(Message::mkInfo, "There are no par-files remain for download for %s", postInfo->GetNzbInfo()->GetName()); postInfo->SetStage(PostInfo::ptQueued); } } #endif if (postInfo->GetDeleted()) { postInfo->SetStage(PostInfo::ptFinished); } if (postInfo->GetStage() == PostInfo::ptQueued && (!g_Options->GetPausePostProcess() || postInfo->GetNzbInfo()->GetForcePriority())) { DeletePostThread(postInfo); StartJob(downloadQueue, postInfo); } else if (postInfo->GetStage() == PostInfo::ptFinished) { UpdatePauseState(false, nullptr); JobCompleted(downloadQueue, postInfo); } else if (!g_Options->GetPausePostProcess()) { error("Internal error: invalid state in post-processor"); // TODO: cancel (delete) current job } } } }